<!DOCTYPE HTML>
<html lang="zh-CN">


<head>
    <meta charset="utf-8">
    <meta name="keywords" content="计算机网络实训, 十二惊惶的gitee">
    <meta name="description" content="实训一阶段1：基本网络通信
要求：
开发一个聊天程序；
包含客户端和服务器端；
编程语言不限；
要能在两台PC上运行。

初级阶段1：socket使用在TCP中，客户端的实现流程：（1）创建客户端的socket对象   （2）建立与服务器之">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <meta name="renderer" content="webkit|ie-stand|ie-comp">
    <meta name="mobile-web-app-capable" content="yes">
    <meta name="format-detection" content="telephone=no">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <meta name="referrer" content="no-referrer-when-downgrade">
    <!-- Global site tag (gtag.js) - Google Analytics -->


    <title>计算机网络实训 | 十二惊惶的gitee</title>
    <link rel="icon" type="image/png" href="/shier_jinghuang/favicon.png">
    


    <!-- bg-cover style     -->



<link rel="stylesheet" type="text/css" href="/shier_jinghuang/libs/awesome/css/all.min.css">
<link rel="stylesheet" type="text/css" href="/shier_jinghuang/libs/materialize/materialize.min.css">
<link rel="stylesheet" type="text/css" href="/shier_jinghuang/libs/aos/aos.css">
<link rel="stylesheet" type="text/css" href="/shier_jinghuang/libs/animate/animate.min.css">
<link rel="stylesheet" type="text/css" href="/shier_jinghuang/libs/lightGallery/css/lightgallery.min.css">
<link rel="stylesheet" type="text/css" href="/shier_jinghuang/css/matery.css">
<link rel="stylesheet" type="text/css" href="/shier_jinghuang/css/my.css">
<link rel="stylesheet" type="text/css" href="/shier_jinghuang/css/dark.css" media="none" onload="if(media!='all')media='all'">




    <link rel="stylesheet" href="/shier_jinghuang/libs/tocbot/tocbot.css">
    <link rel="stylesheet" href="/shier_jinghuang/css/post.css">




    



    <script src="/shier_jinghuang/libs/jquery/jquery-3.6.0.min.js"></script>

<meta name="generator" content="Hexo 5.4.0"><link rel="alternate" href="/shier_jinghuang/atom.xml" title="十二惊惶的gitee" type="application/atom+xml">
</head>


<body>
    <header class="navbar-fixed">
    <nav id="headNav" class="bg-color nav-transparent">
        <div id="navContainer" class="nav-wrapper container">
            <div class="brand-logo">
                <a href="/shier_jinghuang/" class="waves-effect waves-light">
                    
                    <img src="/shier_jinghuang/medias/1.jpg" class="logo-img" alt="LOGO">
                    
                    <span class="logo-span">十二惊惶的gitee</span>
                </a>
            </div>
            

<a href="#" data-target="mobile-nav" class="sidenav-trigger button-collapse"><i class="fas fa-bars"></i></a>
<ul class="right nav-menu">
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/shier_jinghuang/" class="waves-effect waves-light">
      
      <i class="fas fa-home" style="zoom: 0.6;"></i>
      
      <span>首页</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/shier_jinghuang/tags" class="waves-effect waves-light">
      
      <i class="fas fa-tags" style="zoom: 0.6;"></i>
      
      <span>标签</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/shier_jinghuang/categories" class="waves-effect waves-light">
      
      <i class="fas fa-bookmark" style="zoom: 0.6;"></i>
      
      <span>分类</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/shier_jinghuang/archives" class="waves-effect waves-light">
      
      <i class="fas fa-archive" style="zoom: 0.6;"></i>
      
      <span>归档</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/shier_jinghuang/about" class="waves-effect waves-light">
      
      <i class="fas fa-user-circle" style="zoom: 0.6;"></i>
      
      <span>关于</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/shier_jinghuang/contact" class="waves-effect waves-light">
      
      <i class="fas fa-comments" style="zoom: 0.6;"></i>
      
      <span>留言板</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/shier_jinghuang/friends" class="waves-effect waves-light">
      
      <i class="fas fa-address-book" style="zoom: 0.6;"></i>
      
      <span>友情链接</span>
    </a>
    
  </li>
  
  <li>
    <a href="#searchModal" class="modal-trigger waves-effect waves-light">
      <i id="searchIcon" class="fas fa-search" title="搜索" style="zoom: 0.85;"></i>
    </a>
  </li>
  <li>
    <a href="javascript:;" class="waves-effect waves-light" onclick="switchNightMode()" title="深色/浅色模式" >
      <i id="sum-moon-icon" class="fas fa-sun" style="zoom: 0.85;"></i>
    </a>
  </li>
</ul>


<div id="mobile-nav" class="side-nav sidenav">

    <div class="mobile-head bg-color">
        
        <img src="/shier_jinghuang/medias/1.jpg" class="logo-img circle responsive-img">
        
        <div class="logo-name">十二惊惶的gitee</div>
        <div class="logo-desc">
            
            犁牛之子骍且角，虽欲勿用，山川其舍诸
            
        </div>
    </div>

    <ul class="menu-list mobile-menu-list">
        
        <li class="m-nav-item">
	  
		<a href="/shier_jinghuang/" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-home"></i>
			
			首页
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/shier_jinghuang/tags" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-tags"></i>
			
			标签
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/shier_jinghuang/categories" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-bookmark"></i>
			
			分类
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/shier_jinghuang/archives" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-archive"></i>
			
			归档
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/shier_jinghuang/about" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-user-circle"></i>
			
			关于
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/shier_jinghuang/contact" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-comments"></i>
			
			留言板
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/shier_jinghuang/friends" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-address-book"></i>
			
			友情链接
		</a>
          
        </li>
        
        
        <li><div class="divider"></div></li>
        <li>
            <a href="https://gitee.com/Im-so-scared-2/shier_jinghuang" class="waves-effect waves-light" target="_blank">
                <i class="fab fa-github-square fa-fw"></i>十二惊惶
            </a>
        </li>
        
    </ul>
</div>


        </div>

        
            <style>
    .nav-transparent .github-corner {
        display: none !important;
    }

    .github-corner {
        position: absolute;
        z-index: 10;
        top: 0;
        right: 0;
        border: 0;
        transform: scale(1.1);
    }

    .github-corner svg {
        color: #0f9d58;
        fill: #fff;
        height: 64px;
        width: 64px;
    }

    .github-corner:hover .octo-arm {
        animation: a 0.56s ease-in-out;
    }

    .github-corner .octo-arm {
        animation: none;
    }

    @keyframes a {
        0%,
        to {
            transform: rotate(0);
        }
        20%,
        60% {
            transform: rotate(-25deg);
        }
        40%,
        80% {
            transform: rotate(10deg);
        }
    }
</style>

<a href="https://gitee.com/Im-so-scared-2/shier_jinghuang" class="github-corner tooltipped hide-on-med-and-down" target="_blank"
   data-tooltip="十二惊惶" data-position="left" data-delay="50">
    <svg viewBox="0 0 250 250" aria-hidden="true">
        <path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
        <path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"
              fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path>
        <path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"
              fill="currentColor" class="octo-body"></path>
    </svg>
</a>
        
    </nav>

</header>

    



<div class="bg-cover pd-header post-cover" style="background-image: url('/shier_jinghuang/medias/featureimages/22.jpg')">
    <div class="container" style="right: 0px;left: 0px;">
        <div class="row">
            <div class="col s12 m12 l12">
                <div class="brand">
                    <h1 class="description center-align post-title">计算机网络实训</h1>
                </div>
            </div>
        </div>
    </div>
</div>




<main class="post-container content">

    
    <div class="row">
    <div id="main-content" class="col s12 m12 l9">
        <!-- 文章内容详情 -->
<div id="artDetail">
    <div class="card">
        <div class="card-content article-info">
            <div class="row tag-cate">
                <div class="col s7">
                    
                    <div class="article-tag">
                        
                            <a href="/shier_jinghuang/tags/%E5%AE%9E%E8%AE%AD%E8%AE%B0%E5%BD%95/">
                                <span class="chip bg-color">实训记录</span>
                            </a>
                        
                    </div>
                    
                </div>
                <div class="col s5 right-align">
                    
                    <div class="post-cate">
                        <i class="fas fa-bookmark fa-fw icon-category"></i>
                        
                            <a href="/shier_jinghuang/categories/%E7%BD%91%E7%BB%9C%E5%B7%A5%E7%A8%8B%E7%9B%B8%E5%85%B3/" class="post-category">
                                网络工程相关
                            </a>
                        
                    </div>
                    
                </div>
            </div>

            <div class="post-info">
                
                <div class="post-date info-break-policy">
                    <i class="far fa-calendar-minus fa-fw"></i>发布日期:&nbsp;&nbsp;
                    2022-09-08
                </div>
                

                
                <div class="post-date info-break-policy">
                    <i class="far fa-calendar-check fa-fw"></i>更新日期:&nbsp;&nbsp;
                    2022-11-13
                </div>
                

                
                <div class="info-break-policy">
                    <i class="far fa-file-word fa-fw"></i>文章字数:&nbsp;&nbsp;
                    28.1k
                </div>
                

                
                <div class="info-break-policy">
                    <i class="far fa-clock fa-fw"></i>阅读时长:&nbsp;&nbsp;
                    121 分
                </div>
                

                
                    <div id="busuanzi_container_page_pv" class="info-break-policy">
                        <i class="far fa-eye fa-fw"></i>阅读次数:&nbsp;&nbsp;
                        <span id="busuanzi_value_page_pv"></span>
                    </div>
				
            </div>
        </div>
        <hr class="clearfix">

        
        <!-- 是否加载使用自带的 prismjs. -->
        <link rel="stylesheet" href="/shier_jinghuang/libs/prism/prism.min.css">
        

        

        <div class="card-content article-card-content">
            <div id="articleContent">
                <h1 id="实训一阶段1：基本网络通信"><a href="#实训一阶段1：基本网络通信" class="headerlink" title="实训一阶段1：基本网络通信"></a>实训一阶段1：基本网络通信</h1><blockquote>
<p>要求：</p>
<p>开发一个聊天程序；</p>
<p>包含客户端和服务器端；</p>
<p>编程语言不限；</p>
<p>要能在两台PC上运行。</p>
</blockquote>
<h2 id="初级阶段1：socket使用"><a href="#初级阶段1：socket使用" class="headerlink" title="初级阶段1：socket使用"></a>初级阶段1：socket使用</h2><p>在TCP中，客户端的实现流程：（1）创建客户端的socket对象   （2）建立与服务器之间的联系  （3）发送请求  （4）接收数据  （5）关闭连接</p>
<p>服务端的实现流程：（1）创建服务端的socket对象  （2）绑定服务端的地址 （3）设置监听器 （4）等待客户端的连接 （5）接收客户端的请求  （6）返回处理的结果到客户端</p>
<p><img src="https://img-blog.csdn.net/20180115185303067"></p>
<p>**套接字(Socket)**，就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端，提供了应用层进程利用网络协议交换数据的机制。从所处的地位来讲，套接字上联应用进程，下联网络协议栈，是应用程序通过网络协议进行通信的接口，是应用程序与网络协议栈进行交互的接口</p>
<p><strong>应用程序接口</strong>（英语：<strong>A</strong>pplication <strong>P</strong>rogramming <strong>I</strong>nterface，简称：<strong>API</strong>），又称为<strong>应用编程接口</strong>，就是<a target="_blank" rel="noopener" href="https://baike.baidu.com/item/%E8%BD%AF%E4%BB%B6?fromModule=lemma_inlink">软件</a>系统不同组成部分衔接的约定。</p>
<pre class="line-numbers language-none"><code class="language-none">socket编程思路
TCP服务端：
1 创建套接字，绑定套接字到本地IP与端口
   # socket.socket(socket.AF_INET,socket.SOCK_STREAM) , s.bind()
2 开始监听连接                   #s.listen()
3 进入循环，不断接受客户端的连接请求              #s.accept()
4 然后接收传来的数据，并发送给对方数据         #s.recv() , s.sendall()
5 传输完毕后，关闭套接字                     #s.close()

TCP客户端:
1 创建套接字，连接远端地址
       # socket.socket(socket.AF_INET,socket.SOCK_STREAM) , s.connect()
2 连接后发送数据和接收数据          # s.sendall(), s.recv()
3 传输完毕后，关闭套接字          #s.close()<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<blockquote>
<p><strong>subprocess 模块</strong>允许我们启动一个新进程，并连接到它们的输入/输出/错误管道，从而获取返回值。</p>
</blockquote>
<blockquote>
<p>Python3 网络编程</p>
<p>Python 提供了两个级别访问的网络服务。：</p>
<ul>
<li>低级别的网络服务支持基本的 Socket，它提供了标准的 BSD Sockets API，可以访问底层操作系统Socket接口的全部方法。</li>
<li>高级别的网络服务模块 SocketServer， 它提供了服务器中心类，可以简化网络服务器的开发。</li>
</ul>
<p>Socket又称”套接字”，应用程序通常通过”套接字”向网络发出请求或者应答网络请求，使主机间或者一台计算机上的进程间可以通讯。</p>
<p>网络中进程间如何通信，即利用三元组【ip地址，协议，端口】可以进行网络间通信了，那我们应该怎么实现了，因此，我们socket应运而生，它就是利用三元组解决网络通信的一个中间件工具</p>
<p>TCP建立连接时要传输三个数据包，俗称三次握手（Three-way Handshaking）。</p>
<pre class="line-numbers language-csharp" data-language="csharp"><code class="language-csharp"><span class="token punctuation">[</span>Shake <span class="token number">1</span><span class="token punctuation">]</span> 套接字A：“你好，套接字B，我这里有数据要传送给你，建立连接吧。”
<span class="token punctuation">[</span>Shake <span class="token number">2</span><span class="token punctuation">]</span> 套接字B：“好的，我这边已准备就绪。”
<span class="token punctuation">[</span>Shake <span class="token number">3</span><span class="token punctuation">]</span> 套接字A：“谢谢你受理我的请求。<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre>
</blockquote>
<table>
<thead>
<tr>
<th>服务器端套接字</th>
<th></th>
</tr>
</thead>
<tbody><tr>
<td>s.bind()</td>
<td>绑定地址（host,port）到套接字， 在AF_INET下,以元组（host,port）的形式表示地址。</td>
</tr>
<tr>
<td>s.listen()</td>
<td>开始TCP监听。backlog指定在拒绝连接之前，操作系统可以挂起的最大连接数量。该值至少为1，大部分应用程序设为5就可以了。<br/>listen函数中backlog的含义是什么？完成队列的长度 (<a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/78879634">https://zhuanlan.zhihu.com/p/78879634</a>)</td>
</tr>
<tr>
<td>s.accept()</td>
<td>被动接受TCP客户端连接,(阻塞式)等待连接的到来</td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>客户端套接字</th>
<th></th>
</tr>
</thead>
<tbody><tr>
<td>s.connect()</td>
<td>主动初始化TCP服务器连接，。一般address的格式为元组（hostname,port），如果连接出错，返回socket.error错误。</td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>公共用途的套接字函数</th>
<th></th>
</tr>
</thead>
<tbody><tr>
<td>s.recv()</td>
<td>接收TCP数据，数据以字符串形式返回，bufsize指定要接收的最大数据量。flag提供有关消息的其他信息，通常可以忽略。</td>
</tr>
<tr>
<td>s.send()</td>
<td>发送TCP数据，将string中的数据发送到连接的套接字。返回值是要发送的字节数量，该数量可能小于string的字节大小。</td>
</tr>
<tr>
<td>s.close()</td>
<td>关闭套接字</td>
</tr>
</tbody></table>
<h3 id="代码0-1"><a href="#代码0-1" class="headerlink" title="代码0.1"></a><strong>代码0.1</strong></h3><p><strong>作用：可以实现服务端和客户端简单交互，但仅限同一个局域网内，且一对一，只能发送一句话</strong></p>
<pre class="line-numbers language-none"><code class="language-none">错误类型：
1.LookupError: unknown encoding: uft-8
这个错误是记录错误类型的,第一次遇到LookupError ,这个是编码格式本来应该是utf-8 自己打字的时候打错了,打成uft-8 了 所以就出现了这个错误.
2.AttributeError: &#39;tuple&#39; object has no attribute &#39;send&#39;
错误原因： server.accept()的返回值是一对(conn, address)，其中conn是一个新的套接字对象，可用于在连接上发送和接收数据，地址是绑定到连接另一端的套接字的地址。
解决方法：client,addr &#x3D; server.accept()
3.TimeoutError: [WinError 10060] 由于连接方在一段时间后没有正确答复或连接的主机没有反应，连接尝试失败。
防火墙没开放该端口网上找到这个……经过24小时检验：socket仅限在局域网使用，所以……一个热点IP和学校内网一起玩……不可能，想的话买个服务器。所以要么开两个学校电脑，要么就在自己电脑上玩耍。
host&#x3D;&#39;服务器的静态IP&#39;（IPv4地址）
host &#x3D; socket.gethostbyname(socket.gethostname()) （土豆那缺儿，我们一直检验都连不起来原来它是IPv4网关……）
4.
这个时端口号未开放的原因，在防火墙里开放就行<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment">#客户端</span>
<span class="token comment">#客户端IP地址：192.168.55.43</span>
<span class="token comment">#服务器端IP地址：192.168.120.209</span>
<span class="token keyword">import</span> socket

<span class="token comment">#host = socket.gethostname() #获取本地主机名</span>
host <span class="token operator">=</span> <span class="token string">'192.168.31.129'</span>
port <span class="token operator">=</span> <span class="token number">8800</span> <span class="token comment">#设置端口</span>
<span class="token keyword">print</span><span class="token punctuation">(</span>host<span class="token punctuation">)</span>

<span class="token comment">##第一步：创建嵌套字，连接远端地址</span>
client <span class="token operator">=</span> socket<span class="token punctuation">.</span>socket<span class="token punctuation">(</span>socket<span class="token punctuation">.</span>AF_INET<span class="token punctuation">,</span>socket<span class="token punctuation">.</span>SOCK_STREAM<span class="token punctuation">)</span> <span class="token comment">#创建socket对象</span>
client<span class="token punctuation">.</span>connect<span class="token punctuation">(</span><span class="token punctuation">(</span>host<span class="token punctuation">,</span>port<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">#连接服务端，指定主机和端口</span>

<span class="token comment">##第二步：连接后发送数据/接收数据</span>
msg <span class="token operator">=</span> client<span class="token punctuation">.</span>recv<span class="token punctuation">(</span><span class="token number">1024</span><span class="token punctuation">)</span> <span class="token comment">#接收小于1024字节的数据</span>

<span class="token comment">##第三步：传输完毕，关闭嵌套字</span>
client<span class="token punctuation">.</span>close<span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token keyword">print</span><span class="token punctuation">(</span>msg<span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment">#服务端</span>
<span class="token comment">#客户端IP地址：192.168.55.43</span>
<span class="token comment">#服务器端IP地址：192.168.120.209</span>
<span class="token keyword">import</span> socket

<span class="token comment">#host = socket.gethostname() #获取本地主机名</span>
host <span class="token operator">=</span> <span class="token string">'192.168.120.209'</span>
port <span class="token operator">=</span> <span class="token number">8800</span>
<span class="token keyword">print</span><span class="token punctuation">(</span>host<span class="token punctuation">)</span>

<span class="token comment">##第一步：创建嵌套字，绑定套接字到本地IP与端口</span>
server <span class="token operator">=</span> socket<span class="token punctuation">.</span>socket<span class="token punctuation">(</span>socket<span class="token punctuation">.</span>AF_INET<span class="token punctuation">,</span>socket<span class="token punctuation">.</span>SOCK_STREAM<span class="token punctuation">)</span> <span class="token comment">#创建socket对象</span>
server<span class="token punctuation">.</span>bind<span class="token punctuation">(</span><span class="token punctuation">(</span>host<span class="token punctuation">,</span>port<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">#绑定端口号</span>
<span class="token comment">#bind():绑定地址（host,port）到套接字,在AF_INET下,以元组（host,port）的形式表示地址</span>

<span class="token comment">##第二步：监听连接</span>
server<span class="token punctuation">.</span>listen<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token comment">#开始监听;最大连接1台客户端，超过后排队</span>

<span class="token comment">##第三步：进入循环，不断接受客户端的连接请求</span>
<span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
    client<span class="token punctuation">,</span>addr <span class="token operator">=</span> server<span class="token punctuation">.</span>accept<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#创建客户端连接</span>
    <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">"连接地址：%s"</span><span class="token operator">%</span><span class="token builtin">str</span><span class="token punctuation">(</span>addr<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token comment">##第四步：接收传来的数据/发送给对方数据</span>
    msg <span class="token operator">=</span> <span class="token string">'Hello!'</span>
    client<span class="token punctuation">.</span>send<span class="token punctuation">(</span>msg<span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token comment">##第五步：传输完毕后，关闭套接字</span>
    client<span class="token punctuation">.</span>close<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<blockquote>
<p><strong>为什么多个客户端可以连接服务器的同个端口？</strong></p>
<p>我们这里讲Socket连接：<br>1.端口只是一个数字辨识，不是真正的物理端口；<br>2.一个Socket连接的<a target="_blank" rel="noopener" href="https://so.csdn.net/so/search?q=%E4%B8%BB%E9%94%AE&spm=1001.2101.3001.7020">主键</a>（即不同socket之间的区分）是由一个五元组{SRC-IP, SRC-PORT, DEST-IP, DEST-PORT, PROTOCOL}组成，即{源地址，源端口，目标地址，目标端口，协议}组成，那些说四元组不包含协议的说法是错误的。<br>3.一个进程可以拥有多个socket连接。</p>
<p>例子一、两个客户端连接在同个服务器的同个端口80，即有两个socket连接：<br>- socket1 {SRC-A, 100, DEST-X,80, TCP}<br>- socket2{SRC-B, 100, DEST-X,80, TCP}<br>主机A和主机B的地址不同，两台主机同时连接到服务器X的80端口。服务器要怎么处理这个连接是它的事，我们要理解的是为什么一个主机同个端口能监听多个客户端Socket连接。</p>
<p>解释：<br>1.是因为两个客户端的IP不同，服务器能识别出不同的Socket；<br>2.即使IP地址相同，端口不同，服务器也能够分辨；<br>3.只要服务器知道收到的请求和哪个socket相关，那么它就能使用这个socket正确地回复那个客户端；<br>4.如果对于不同的socket需要不同的端口，那么不仅仅浪费服务器资源，而且每次客户端连接上serverSocket之后还要另外分配新的端口和客户端通信。没必要。</p>
<p>例子二、不同的进程可以监听同一个端口。</p>
<ol>
<li>因此在服务器的两个使用不同协议的进程可以监听同一个端口。</li>
<li>如果一个socket的辨识只是四元组不包括协议{SRC-IP, SRC-PORT, DEST-IP, DEST-PORT}，那么不同进程是不可能同时监听同一个端口的。没有协议的话一个客户端连接到同一台某个有两个进程监听端口的服务器，那么就没有什么机制可以确定客户端是要连接哪一个进程了。</li>
</ol>
<p>总结：</p>
<ol>
<li>不同协议可以监听同一个端口（不管是不是在服务器的同个进程）</li>
<li>某个协议的进程可以监听多个客户端的连接，因为只要五元组不同进程就能分辨。</li>
<li>从上面的例子可以知道，客户端同个进程也可以在同个端口用不同的协议与客户端建立连接。</li>
</ol>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://www.jianshu.com/p/066d99da7cbd">一、Socket技术详解 - 简书 (jianshu.com)</a></p>
<h3 id="代码0-2"><a href="#代码0-2" class="headerlink" title="代码0.2"></a><strong>代码0.2</strong></h3><p><strong>作用：在0.1基础上，实现服务器接收数据，客户端发送数据</strong></p>
<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment">#服务端</span>
<span class="token keyword">import</span> socket

host <span class="token operator">=</span> socket<span class="token punctuation">.</span>gethostname<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#获取本地主机名</span>
port <span class="token operator">=</span> <span class="token number">9999</span>
<span class="token keyword">print</span><span class="token punctuation">(</span>host<span class="token punctuation">)</span>

<span class="token comment">##第一步：创建嵌套字，绑定套接字到本地IP与端口</span>
server <span class="token operator">=</span> socket<span class="token punctuation">.</span>socket<span class="token punctuation">(</span>socket<span class="token punctuation">.</span>AF_INET<span class="token punctuation">,</span>socket<span class="token punctuation">.</span>SOCK_STREAM<span class="token punctuation">)</span> <span class="token comment">#创建socket对象</span>
server<span class="token punctuation">.</span>bind<span class="token punctuation">(</span><span class="token punctuation">(</span>host<span class="token punctuation">,</span>port<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">#绑定端口号</span>
<span class="token comment">#bind():绑定地址（host,port）到套接字,在AF_INET下,以元组（host,port）的形式表示地址</span>

<span class="token comment">##第二步：监听连接</span>
server<span class="token punctuation">.</span>listen<span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span> <span class="token comment">#开始监听;最大连接1台客户端，超过后排队</span>

<span class="token comment">##第三步：进入循环，不断接受客户端的连接请求</span>
<span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
    client<span class="token punctuation">,</span>addr <span class="token operator">=</span> server<span class="token punctuation">.</span>accept<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#创建客户端连接</span>
    <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">"连接地址：%s"</span><span class="token operator">%</span><span class="token builtin">str</span><span class="token punctuation">(</span>addr<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token comment">##第四步：接收传来的数据和转发对方数据</span>
    msg <span class="token operator">=</span> client<span class="token punctuation">.</span>recv<span class="token punctuation">(</span><span class="token number">1024</span><span class="token punctuation">)</span> <span class="token comment">#接收小于1024字节的数据</span>
    <span class="token keyword">print</span><span class="token punctuation">(</span>msg<span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token comment">##第五步：传输完毕后，关闭套接字</span>
    client<span class="token punctuation">.</span>close<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment">#客户端</span>
<span class="token keyword">import</span> socket

host <span class="token operator">=</span> socket<span class="token punctuation">.</span>gethostname<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#获取本地主机名</span>
<span class="token comment">#host = socket.gethostbyname(socket.gethostname())</span>
<span class="token comment">#host = '39.144.108.89'</span>
port <span class="token operator">=</span> <span class="token number">9999</span> <span class="token comment">#设置端口</span>
<span class="token keyword">print</span><span class="token punctuation">(</span>host<span class="token punctuation">)</span>

<span class="token comment">##第一步：创建嵌套字，连接远端地址</span>
client <span class="token operator">=</span> socket<span class="token punctuation">.</span>socket<span class="token punctuation">(</span>socket<span class="token punctuation">.</span>AF_INET<span class="token punctuation">,</span>socket<span class="token punctuation">.</span>SOCK_STREAM<span class="token punctuation">)</span> <span class="token comment">#创建socket对象</span>
client<span class="token punctuation">.</span>connect<span class="token punctuation">(</span><span class="token punctuation">(</span>host<span class="token punctuation">,</span>port<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">#连接服务端，指定主机和端口</span>

<span class="token comment">##第二步：连接后发送数据/接收数据</span>
msg <span class="token operator">=</span> <span class="token string">'Hello!'</span>
client<span class="token punctuation">.</span>send<span class="token punctuation">(</span>msg<span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">##第三步：传输完毕，关闭嵌套字</span>
client<span class="token punctuation">.</span>close<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h3 id="代码0-3"><a href="#代码0-3" class="headerlink" title="代码0.3"></a><strong>代码0.3</strong></h3><p><strong>作用：在0.2基础上，实现可传可接收，但存在问题，未解决</strong></p>
<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment">#服务端</span>
<span class="token keyword">import</span> socket

host <span class="token operator">=</span> socket<span class="token punctuation">.</span>gethostname<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#获取本地主机名</span>
<span class="token comment">#host = '192.168.120.29' #服务端IP地址</span>
port <span class="token operator">=</span> <span class="token number">8800</span>
max_connect <span class="token operator">=</span> <span class="token number">1</span> <span class="token comment">#最大连接客户端数</span>
max_receive_data <span class="token operator">=</span> <span class="token number">1024</span> <span class="token comment">#最大接收字节数</span>
server_name <span class="token operator">=</span> <span class="token string">'老王'</span> <span class="token comment">#设置用户名</span>

<span class="token comment">##第一步：创建嵌套字，绑定套接字到本地IP与端口</span>
server <span class="token operator">=</span> socket<span class="token punctuation">.</span>socket<span class="token punctuation">(</span>socket<span class="token punctuation">.</span>AF_INET<span class="token punctuation">,</span>socket<span class="token punctuation">.</span>SOCK_STREAM<span class="token punctuation">)</span> <span class="token comment">#创建socket对象</span>
server<span class="token punctuation">.</span>bind<span class="token punctuation">(</span><span class="token punctuation">(</span>host<span class="token punctuation">,</span>port<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">#绑定端口号</span>

<span class="token comment">##第二步：监听连接</span>
server<span class="token punctuation">.</span>listen<span class="token punctuation">(</span>max_connect<span class="token punctuation">)</span> <span class="token comment">#开始监听;最大连接1台客户端，超过后排队</span>
<span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'Server is ready.'</span><span class="token punctuation">)</span>

<span class="token comment">##第三步：进入循环，不断接受客户端的连接请求</span>
<span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
    client<span class="token punctuation">,</span>addr <span class="token operator">=</span> server<span class="token punctuation">.</span>accept<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#创建客户端连接</span>
    <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">"连接地址：%s"</span><span class="token operator">%</span><span class="token builtin">str</span><span class="token punctuation">(</span>addr<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token comment">##第四步：接收传来的数据/发送给对方数据</span>
    <span class="token comment">#发送数据</span>
    send_msg <span class="token operator">=</span> <span class="token builtin">input</span><span class="token punctuation">(</span><span class="token string">'请输入：'</span><span class="token punctuation">)</span>
    send_msg <span class="token operator">=</span> server_name <span class="token operator">+</span> <span class="token string">': '</span><span class="token operator">+</span> send_msg
    client<span class="token punctuation">.</span>send<span class="token punctuation">(</span>send_msg<span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">if</span> send_msg <span class="token operator">==</span> <span class="token string">'close'</span><span class="token punctuation">:</span>
        <span class="token keyword">break</span>
    <span class="token comment">#接收数据</span>
    receive_msg <span class="token operator">=</span> client<span class="token punctuation">.</span>recv<span class="token punctuation">(</span>max_receive_data<span class="token punctuation">)</span>
    <span class="token keyword">print</span><span class="token punctuation">(</span>receive_msg<span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    
<span class="token comment">##第五步：传输完毕后，关闭套接字</span>
client<span class="token punctuation">.</span>close<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment">#客户端</span>
<span class="token keyword">import</span> socket

host <span class="token operator">=</span> socket<span class="token punctuation">.</span>gethostname<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#获取本地主机名</span>
<span class="token comment">#host = '192.168.31.129' #服务端IP地址</span>
port <span class="token operator">=</span> <span class="token number">8800</span> <span class="token comment">#设置端口</span>
max_receive_data <span class="token operator">=</span> <span class="token number">1024</span> <span class="token comment">#最大接收字节数</span>
client_name <span class="token operator">=</span> <span class="token string">'老刘'</span> <span class="token comment">#设置用户名</span>

<span class="token comment">##第一步：创建嵌套字，连接远端地址</span>
client <span class="token operator">=</span> socket<span class="token punctuation">.</span>socket<span class="token punctuation">(</span>socket<span class="token punctuation">.</span>AF_INET<span class="token punctuation">,</span>socket<span class="token punctuation">.</span>SOCK_STREAM<span class="token punctuation">)</span> <span class="token comment">#创建socket对象</span>
client<span class="token punctuation">.</span>connect<span class="token punctuation">(</span><span class="token punctuation">(</span>host<span class="token punctuation">,</span>port<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">#连接服务端，指定主机和端口</span>
<span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'Connecting is successful!'</span><span class="token punctuation">)</span>

<span class="token comment">##第二步：连接后发送数据/接收数据</span>
<span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
    <span class="token comment">#接收数据</span>
    receive_msg <span class="token operator">=</span> client<span class="token punctuation">.</span>recv<span class="token punctuation">(</span>max_receive_data<span class="token punctuation">)</span>
    <span class="token keyword">print</span><span class="token punctuation">(</span>receive_msg<span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">if</span> receive_msg<span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token operator">==</span><span class="token string">'close'</span><span class="token punctuation">:</span>
        <span class="token keyword">break</span>
    <span class="token comment">#发送数据</span>
    send_msg <span class="token operator">=</span> <span class="token builtin">input</span><span class="token punctuation">(</span><span class="token string">'请输入：'</span><span class="token punctuation">)</span>
    send_msg <span class="token operator">=</span> client_name <span class="token operator">+</span> <span class="token string">': '</span><span class="token operator">+</span> send_msg
    client<span class="token punctuation">.</span>send<span class="token punctuation">(</span>send_msg<span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    
<span class="token comment">##第三步：传输完毕，关闭嵌套字</span>
client<span class="token punctuation">.</span>close<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<h2 id="初级阶段2：hreading使用"><a href="#初级阶段2：hreading使用" class="headerlink" title="初级阶段2：hreading使用"></a>初级阶段2：hreading使用</h2><pre class="line-numbers language-none"><code class="language-none">服务器端的套接字起到监听的作用（类似电话主机），每连接成功一个客户端，就返回一个和客户端通信的套接字（类似电话的分机），服务器端用每个“分机”和每个客户端进行通信。
因为我们使用的是默认的阻塞套接字，服务器和每个客户端通信的过程都是阻塞的，所以，为了服务器可以“同时”（并发）和客户端进行通信，我们用到了多线程。<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre>

<blockquote>
<p>hreading(多线程)模块中包含了关于线程操作的丰富功能，包括：常用线程函数，线程对象，锁对象，递归锁对象，事件对象，条件变量对象，信号量对象，定时器对象，栅栏对象。</p>
<p>创建 Thread 对象有 2 种手段：</p>
<p>1.直接创建 Thread ，将一个 callable 对象从类的构造器传递进去，这个 callable 就是回调函数，用来处理任务。<br>2.<strong>编写一个自定义类继承 Thread，然后复写 run() 方法，在 run() 方法中编写任务处理代码，然后创建这个 Thread 的子类。</strong></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/briblue/article/details/85101144">(29条消息) Python多线程编程(一）：threading 模块 Thread 类的用法详解_frank909的博客-CSDN博客_python threading</a></p>
</blockquote>
<blockquote>
<p>Python 将一个列表里面的元素拼接成一个字符串:</p>
<p>注意: 1. 列表里面的元素必须全是字符串才可以使用join()进行拼接</p>
<p>　　 2. 返回的是一个字符串</p>
<pre class="line-numbers language-python" data-language="python"><code class="language-python">item1 <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">"lowman"</span><span class="token punctuation">,</span> <span class="token string">"isbusy"</span><span class="token punctuation">]</span>
item2 <span class="token operator">=</span> <span class="token string">","</span><span class="token punctuation">.</span>join<span class="token punctuation">(</span>item1<span class="token punctuation">)</span> <span class="token comment"># 根据实际需要使用相应的分隔符连接列表元素,如 , : ; 或者空字符串</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre>
</blockquote>
<blockquote>
<p>Thread.setDaemon(false)设置为用户线程；通过Thread.setDaemon(true)设置为守护线程。如果不设置次属性，默认为用户线程。</p>
<p>用户线程和守护线程的区别：</p>
<p>1.主线程结束后用户线程还会继续运行,JVM存活；主线程结束后守护线程和JVM的状态又下面第2条确定。</p>
<p>2.如果没有用户线程，都是守护线程，那么JVM结束（随之而来的是所有的一切烟消云散，包括所有的守护线程）。</p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/xyls12345/article/details/26256693">(29条消息) Thread.setDaemon详解_starfe-geek的博客-CSDN博客_thread.setdeamon</a></p>
</blockquote>
<table>
<thead>
<tr>
<th>Threading模块的对象</th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td>Thread</td>
<td>线程对象</td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>Threading模块的<a target="_blank" rel="noopener" href="https://so.csdn.net/so/search?q=Thread%E7%B1%BB&spm=1001.2101.3001.7020">Thread类</a></th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td>name</td>
<td>线程名（属性）</td>
</tr>
<tr>
<td>ident</td>
<td>线程标识符（属性）</td>
</tr>
<tr>
<td>daemon</td>
<td>线程是否是守护线程（属性）</td>
</tr>
<tr>
<td><em>init</em>(group=None, tatget=None, name=None, args=(),kwargs ={}, verbose=None, daemon=None)</td>
<td>实例化一个线程对象，需要有一个可调用的 target，以及其参数 args或 kwargs。还可以传递 name 或 group 参数，不过后者还未实现。此外， verbose 标 志 也 是 可 接 受 的。 而 daemon 的 值 将 会 设定thread.daemon 属性/标志</td>
</tr>
<tr>
<td>start()</td>
<td>开启线程</td>
</tr>
<tr>
<td>run()</td>
<td>定义线程功能的方法（通常在子类中被应用开发者重写）</td>
</tr>
</tbody></table>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/wqx521/article/details/82754617">(29条消息) Python3——多线程之threading模块_a1314521531的博客-CSDN博客_python3 threading</a></p>
<blockquote>
<p><a target="_blank" rel="noopener" href="https://www.cnblogs.com/klchang/p/4635040.html">Python中获取异常（Exception）信息</a></p>
<p>repr(e)</p>
<p>给出较全的异常信息，包括异常信息的类型，如1/0的异常信息</p>
<p>“ZeroDivisionError(‘integer division or modulo by zero’,)”</p>
</blockquote>
<h3 id="代码0-4"><a href="#代码0-4" class="headerlink" title="代码0.4"></a><strong>代码0.4</strong></h3><p><strong>作用：在0.3基础上实现多客户端交流，但发送数据和接收数据（显示）安排不合理</strong></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/wyn1564464568/article/details/122891038">(29条消息) python实现简易聊天室程序_Castria的博客-CSDN博客_python聊天室项目代码</a></p>
<blockquote>
<p>首先服务器端创建ServerSocket对象，等待客户连接。</p>
<p>每当有一个客户连接上时，使用一个线程保存其Socket，把该线程保存在一个HashMap集合中。</p>
<p>客户端有信息发送给服务器时，服务器先获取要接收者用户名，根据用户名获取保存的线程（如果没有找到该线程则回发给发送者消息提示其需要联系的用户未上线），再根据该线程创建输出流，把消息转发给接收者。</p>
</blockquote>
<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment">#服务器</span>
<span class="token keyword">import</span> socket
<span class="token keyword">import</span> threading

host <span class="token operator">=</span> socket<span class="token punctuation">.</span>gethostname<span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token comment"># 获取本地主机名</span>
port <span class="token operator">=</span> <span class="token number">9999</span>  <span class="token comment"># 设置端口</span>
max_connect <span class="token operator">=</span> <span class="token number">2</span>  <span class="token comment"># 设置最大连接客户端数</span>
max_recedata <span class="token operator">=</span> <span class="token number">1024</span>  <span class="token comment"># 设置最大接收字节数</span>
<span class="token keyword">print</span><span class="token punctuation">(</span>host<span class="token punctuation">)</span>

server <span class="token operator">=</span> socket<span class="token punctuation">.</span>socket<span class="token punctuation">(</span>socket<span class="token punctuation">.</span>AF_INET<span class="token punctuation">,</span> socket<span class="token punctuation">.</span>SOCK_STREAM<span class="token punctuation">)</span>  <span class="token comment"># 创建socket对象</span>
server<span class="token punctuation">.</span>bind<span class="token punctuation">(</span><span class="token punctuation">(</span>host<span class="token punctuation">,</span> port<span class="token punctuation">)</span><span class="token punctuation">)</span>  <span class="token comment"># 绑定端口号</span>
server<span class="token punctuation">.</span>listen<span class="token punctuation">(</span>max_connect<span class="token punctuation">)</span>  <span class="token comment"># 开始监听;最大连接2台客户端，超过后排队</span>
<span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'ServerSocket is ready.'</span><span class="token punctuation">)</span>

cnt <span class="token operator">=</span> <span class="token number">0</span>  <span class="token comment"># 当前在线人数</span>
textList <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>  <span class="token comment"># 存储历史记录</span>
socketList <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>  <span class="token comment"># 存储已有客户端（套接字）</span>


<span class="token comment"># 自定义类继承，重写run()方法</span>
<span class="token keyword">class</span> <span class="token class-name">ThreadCreate</span><span class="token punctuation">(</span>threading<span class="token punctuation">.</span>Thread<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">def</span> <span class="token function">__init__</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> client<span class="token punctuation">)</span><span class="token punctuation">:</span>  <span class="token comment"># 线程初始化</span>
        threading<span class="token punctuation">.</span>Thread<span class="token punctuation">.</span>__init__<span class="token punctuation">(</span>self<span class="token punctuation">)</span>  <span class="token comment"># 当作Thread的固定结构吧……</span>
        self<span class="token punctuation">.</span>client <span class="token operator">=</span> client  <span class="token comment"># 保存嵌套字（客户端）</span>
        socketList<span class="token punctuation">.</span>append<span class="token punctuation">(</span>client<span class="token punctuation">)</span>  <span class="token comment"># 把嵌套字存在列表里</span>

    <span class="token keyword">def</span> <span class="token function">run</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword">try</span><span class="token punctuation">:</span>
            <span class="token keyword">global</span> cnt
            <span class="token keyword">for</span> sock <span class="token keyword">in</span> socketList<span class="token punctuation">:</span>
                <span class="token keyword">if</span> sock <span class="token operator">==</span> self<span class="token punctuation">.</span>client<span class="token punctuation">:</span>
                    sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'Old client.There are %d presons.'</span><span class="token operator">%</span><span class="token punctuation">(</span>cnt<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token keyword">else</span><span class="token punctuation">:</span>
                    sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'New Client is Coming.There are %d presons.'</span><span class="token operator">%</span><span class="token punctuation">(</span>cnt<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
            <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
                word <span class="token operator">=</span> self<span class="token punctuation">.</span>client<span class="token punctuation">.</span>recv<span class="token punctuation">(</span>max_recedata<span class="token punctuation">)</span><span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#接收数据</span>
                textList<span class="token punctuation">.</span>append<span class="token punctuation">(</span>word<span class="token punctuation">)</span> <span class="token comment">#生成历史记录</span>
                <span class="token keyword">for</span> sock <span class="token keyword">in</span> socketList<span class="token punctuation">:</span> <span class="token comment">#给所有客户端发送新消息</span>
                    sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token operator">+</span>word<span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token keyword">except</span> Exception <span class="token keyword">as</span> e<span class="token punctuation">:</span> <span class="token comment">#客户端强制断开连接（关闭窗口）</span>
            <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token builtin">repr</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">#如何加一个时间戳？</span>
            cnt <span class="token operator">=</span> cnt<span class="token operator">-</span><span class="token number">1</span>
            <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'Lose one person.There are %d persons.'</span><span class="token operator">%</span><span class="token punctuation">(</span>cnt<span class="token punctuation">)</span><span class="token punctuation">)</span>
            socketList<span class="token punctuation">.</span>remove<span class="token punctuation">(</span>self<span class="token punctuation">.</span>client<span class="token punctuation">)</span> <span class="token comment">#移除该客户端</span>
            <span class="token keyword">for</span> sock <span class="token keyword">in</span> socketList<span class="token punctuation">:</span>
                sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'Lose one person.There are %d persons.'</span><span class="token operator">%</span><span class="token punctuation">(</span>cnt<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>


<span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
    client<span class="token punctuation">,</span> addr <span class="token operator">=</span> server<span class="token punctuation">.</span>accept<span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token comment"># 创建客户端连接，每次接收一个连接</span>
    <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">"连接地址：%s"</span> <span class="token operator">%</span> <span class="token builtin">str</span><span class="token punctuation">(</span>addr<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">try</span><span class="token punctuation">:</span>
        <span class="token comment"># 关于历史记录的处理</span>
        <span class="token keyword">if</span> <span class="token builtin">len</span><span class="token punctuation">(</span>textList<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">:</span>
            client<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token string">'No message.'</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token keyword">else</span><span class="token punctuation">:</span>
            client<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">.</span>join<span class="token punctuation">(</span>textList<span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

        cnt <span class="token operator">=</span> cnt <span class="token operator">+</span> <span class="token number">1</span>  <span class="token comment"># 来了一个人加一</span>

        <span class="token comment"># 给用户创建新进程</span>
        newThread <span class="token operator">=</span> ThreadCreate<span class="token punctuation">(</span>client<span class="token punctuation">)</span>
        newThread<span class="token punctuation">.</span>setDaemon<span class="token punctuation">(</span><span class="token boolean">True</span><span class="token punctuation">)</span>  <span class="token comment"># 设置为守护线程</span>
        newThread<span class="token punctuation">.</span>start<span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token comment"># 开启线程</span>

        <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'Connecting is successful!The number of people is '</span> <span class="token operator">+</span> <span class="token builtin">str</span><span class="token punctuation">(</span>cnt<span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token string">'.'</span><span class="token punctuation">)</span>
    <span class="token keyword">except</span> Exception <span class="token keyword">as</span> e<span class="token punctuation">:</span>
        <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token builtin">repr</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token comment"># finally:</span>
    <span class="token comment">#     client.close()</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment">#客户端</span>
<span class="token keyword">import</span> socket
<span class="token keyword">import</span> threading

server_host <span class="token operator">=</span> socket<span class="token punctuation">.</span>gethostname<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#获取本地主机名</span>
server_port <span class="token operator">=</span> <span class="token number">9999</span> <span class="token comment">#设置端口</span>
max_recedata <span class="token operator">=</span> <span class="token number">1024</span>  <span class="token comment"># 设置最大接收字节数</span>
client_name <span class="token operator">=</span> <span class="token string">'Nacy'</span>
<span class="token keyword">print</span><span class="token punctuation">(</span>server_host<span class="token punctuation">)</span>

client <span class="token operator">=</span> socket<span class="token punctuation">.</span>socket<span class="token punctuation">(</span>socket<span class="token punctuation">.</span>AF_INET<span class="token punctuation">,</span>socket<span class="token punctuation">.</span>SOCK_STREAM<span class="token punctuation">)</span> <span class="token comment">#创建socket对象</span>
<span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'Connecting......'</span><span class="token punctuation">)</span>
client<span class="token punctuation">.</span>connect<span class="token punctuation">(</span><span class="token punctuation">(</span>server_host<span class="token punctuation">,</span>server_port<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">#连接服务端，指定主机和端口</span>
<span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'Connecting is successful!'</span><span class="token punctuation">)</span>

msg <span class="token operator">=</span> client<span class="token punctuation">.</span>recv<span class="token punctuation">(</span>max_recedata<span class="token punctuation">)</span> <span class="token comment">#先接收历史消息</span>
<span class="token keyword">if</span> msg<span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token operator">!=</span><span class="token string">'No message.'</span><span class="token punctuation">:</span>
    <span class="token keyword">print</span><span class="token punctuation">(</span>msg<span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token operator">+</span><span class="token string">'\n------以上是历史消息------\n'</span><span class="token punctuation">)</span>

<span class="token comment">#接收文字的线程</span>
<span class="token comment">#由于用户的发送和接收消息是不同步的，在接收消息时线程会阻塞，所以另开启一个线程进行接收文字</span>
<span class="token keyword">class</span> <span class="token class-name">ThreadReceive</span><span class="token punctuation">(</span>threading<span class="token punctuation">.</span>Thread<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">def</span> <span class="token function">__init__</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span>
        threading<span class="token punctuation">.</span>Thread<span class="token punctuation">.</span>__init__<span class="token punctuation">(</span>self<span class="token punctuation">)</span>
    <span class="token keyword">def</span> <span class="token function">run</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
            receive_msg <span class="token operator">=</span> client<span class="token punctuation">.</span>recv<span class="token punctuation">(</span>max_recedata<span class="token punctuation">)</span>
            <span class="token keyword">print</span><span class="token punctuation">(</span>receive_msg<span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
textThread <span class="token operator">=</span> ThreadReceive<span class="token punctuation">(</span><span class="token punctuation">)</span>
textThread<span class="token punctuation">.</span>start<span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">#发送文字</span>
<span class="token keyword">def</span> <span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
        send_msg <span class="token operator">=</span> <span class="token builtin">input</span><span class="token punctuation">(</span><span class="token string">'请输入：'</span><span class="token punctuation">)</span>
        <span class="token keyword">if</span> send_msg<span class="token operator">==</span><span class="token string">'0'</span><span class="token punctuation">:</span>
            <span class="token keyword">break</span>
        client<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span>client_name<span class="token operator">+</span><span class="token string">': '</span><span class="token operator">+</span>send_msg<span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

send<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h3 id="代码0-5"><a href="#代码0-5" class="headerlink" title="代码0.5"></a><strong>代码0.5</strong></h3><p><strong>作用：在0.4基础上加了时间戳，将input里的字符删了，直接输就行……</strong></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/cheneykl/article/details/79717160">(29条消息) Python 给某个文件名添加时间戳_cheney康的博客-CSDN博客</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/drdairen/article/details/60962439">(29条消息) python：threading.Thread类的使用详解_啊啊啊西吧的博客-CSDN博客_python thread</a></p>
<p><a target="_blank" rel="noopener" href="https://www.yisu.com/zixun/720956.html">python中的多线程锁lock=threading.Lock()如何使用 - 开发技术 - 亿速云 (yisu.com)</a></p>
<pre class="line-numbers language-none"><code class="language-none">mutex &#x3D; threading.Lock()
#锁的使用
#创建锁
mutex &#x3D; threading.Lock()
#锁定
mutex.acquire([timeout])
#释放
mutex.release()<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p>发现没啥要修改的……</p>
<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment">#服务端import socket</span>
<span class="token keyword">import</span> socket
<span class="token keyword">import</span> threading

host <span class="token operator">=</span> socket<span class="token punctuation">.</span>gethostname<span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token comment"># 获取本地主机名</span>
port <span class="token operator">=</span> <span class="token number">9999</span>  <span class="token comment"># 设置端口</span>
max_connect <span class="token operator">=</span> <span class="token number">2</span>  <span class="token comment"># 设置最大连接客户端数</span>
max_recedata <span class="token operator">=</span> <span class="token number">1024</span>  <span class="token comment"># 设置最大接收字节数</span>
<span class="token keyword">print</span><span class="token punctuation">(</span>host<span class="token punctuation">)</span>

server <span class="token operator">=</span> socket<span class="token punctuation">.</span>socket<span class="token punctuation">(</span>socket<span class="token punctuation">.</span>AF_INET<span class="token punctuation">,</span> socket<span class="token punctuation">.</span>SOCK_STREAM<span class="token punctuation">)</span>  <span class="token comment"># 创建socket对象</span>
server<span class="token punctuation">.</span>bind<span class="token punctuation">(</span><span class="token punctuation">(</span>host<span class="token punctuation">,</span> port<span class="token punctuation">)</span><span class="token punctuation">)</span>  <span class="token comment"># 绑定端口号</span>
server<span class="token punctuation">.</span>listen<span class="token punctuation">(</span>max_connect<span class="token punctuation">)</span>  <span class="token comment"># 开始监听;最大连接2台客户端，超过后排队</span>
<span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'ServerSocket is ready.'</span><span class="token punctuation">)</span>

cnt <span class="token operator">=</span> <span class="token number">0</span>  <span class="token comment"># 当前在线人数</span>
textList <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>  <span class="token comment"># 存储历史记录</span>
socketList <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>  <span class="token comment"># 存储已有客户端（套接字）</span>


<span class="token comment"># 自定义类继承，重写run()方法</span>
<span class="token keyword">class</span> <span class="token class-name">ThreadCreate</span><span class="token punctuation">(</span>threading<span class="token punctuation">.</span>Thread<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">def</span> <span class="token function">__init__</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> client<span class="token punctuation">)</span><span class="token punctuation">:</span>  <span class="token comment"># 线程初始化</span>
        threading<span class="token punctuation">.</span>Thread<span class="token punctuation">.</span>__init__<span class="token punctuation">(</span>self<span class="token punctuation">)</span>  <span class="token comment"># 当作Thread的固定结构吧……</span>
        self<span class="token punctuation">.</span>client <span class="token operator">=</span> client  <span class="token comment"># 保存嵌套字（客户端）</span>
        socketList<span class="token punctuation">.</span>append<span class="token punctuation">(</span>client<span class="token punctuation">)</span>  <span class="token comment"># 把嵌套字存在列表里</span>

    <span class="token keyword">def</span> <span class="token function">run</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword">try</span><span class="token punctuation">:</span>
            <span class="token keyword">global</span> cnt
            <span class="token keyword">for</span> sock <span class="token keyword">in</span> socketList<span class="token punctuation">:</span>
                <span class="token keyword">if</span> sock <span class="token operator">==</span> self<span class="token punctuation">.</span>client<span class="token punctuation">:</span>
                    sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'Welcome!There are %d presons.'</span><span class="token operator">%</span><span class="token punctuation">(</span>cnt<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token keyword">else</span><span class="token punctuation">:</span>
                    sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'New Client is Coming.There are %d presons.'</span><span class="token operator">%</span><span class="token punctuation">(</span>cnt<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
            <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
                word <span class="token operator">=</span> self<span class="token punctuation">.</span>client<span class="token punctuation">.</span>recv<span class="token punctuation">(</span>max_recedata<span class="token punctuation">)</span><span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#接收数据</span>
                textList<span class="token punctuation">.</span>append<span class="token punctuation">(</span>word<span class="token punctuation">)</span> <span class="token comment">#生成历史记录</span>
                <span class="token keyword">for</span> sock <span class="token keyword">in</span> socketList<span class="token punctuation">:</span> <span class="token comment">#给所有客户端发送新消息</span>
                    sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token operator">+</span>word<span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token keyword">except</span> Exception <span class="token keyword">as</span> e<span class="token punctuation">:</span> <span class="token comment">#客户端强制断开连接（关闭窗口）</span>
            <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token builtin">repr</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">#如何加一个时间戳？</span>
            cnt <span class="token operator">=</span> cnt<span class="token operator">-</span><span class="token number">1</span>
            <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'Lose one person.There are %d persons.'</span><span class="token operator">%</span><span class="token punctuation">(</span>cnt<span class="token punctuation">)</span><span class="token punctuation">)</span>
            socketList<span class="token punctuation">.</span>remove<span class="token punctuation">(</span>self<span class="token punctuation">.</span>client<span class="token punctuation">)</span> <span class="token comment">#移除该客户端</span>
            <span class="token keyword">for</span> sock <span class="token keyword">in</span> socketList<span class="token punctuation">:</span>
                sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'Lose one person.There are %d persons.'</span><span class="token operator">%</span><span class="token punctuation">(</span>cnt<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>


<span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
    client<span class="token punctuation">,</span> addr <span class="token operator">=</span> server<span class="token punctuation">.</span>accept<span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token comment"># 创建客户端连接，每次接收一个连接</span>
    <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">"连接地址：%s"</span> <span class="token operator">%</span> <span class="token builtin">str</span><span class="token punctuation">(</span>addr<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">try</span><span class="token punctuation">:</span>
        <span class="token comment"># 关于历史记录的处理</span>
        <span class="token keyword">if</span> <span class="token builtin">len</span><span class="token punctuation">(</span>textList<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">:</span>
            client<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token string">'No message.'</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token keyword">else</span><span class="token punctuation">:</span>
            client<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">.</span>join<span class="token punctuation">(</span>textList<span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

        cnt <span class="token operator">=</span> cnt <span class="token operator">+</span> <span class="token number">1</span>  <span class="token comment"># 来了一个人加一</span>

        <span class="token comment"># 给用户创建新进程</span>
        newThread <span class="token operator">=</span> ThreadCreate<span class="token punctuation">(</span>client<span class="token punctuation">)</span>
        newThread<span class="token punctuation">.</span>setDaemon<span class="token punctuation">(</span><span class="token boolean">True</span><span class="token punctuation">)</span>  <span class="token comment"># 设置为守护线程</span>
        newThread<span class="token punctuation">.</span>start<span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token comment"># 开启线程</span>

        <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'Connecting is successful!The number of people is '</span> <span class="token operator">+</span> <span class="token builtin">str</span><span class="token punctuation">(</span>cnt<span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token string">'.'</span><span class="token punctuation">)</span>
    <span class="token keyword">except</span> Exception <span class="token keyword">as</span> e<span class="token punctuation">:</span>
        <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token builtin">repr</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token comment"># finally:</span>
    <span class="token comment">#     client.close()</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment">#客户端</span>
<span class="token keyword">import</span> threading

server_host <span class="token operator">=</span> socket<span class="token punctuation">.</span>gethostname<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#获取本地主机名</span>
server_port <span class="token operator">=</span> <span class="token number">9999</span> <span class="token comment">#设置端口</span>
max_recedata <span class="token operator">=</span> <span class="token number">1024</span>  <span class="token comment"># 设置最大接收字节数</span>
client_name <span class="token operator">=</span> <span class="token string">'Helen'</span>
<span class="token keyword">print</span><span class="token punctuation">(</span>server_host<span class="token punctuation">)</span>
lock <span class="token operator">=</span> threading<span class="token punctuation">.</span>Lock<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#创建锁</span>

client <span class="token operator">=</span> socket<span class="token punctuation">.</span>socket<span class="token punctuation">(</span>socket<span class="token punctuation">.</span>AF_INET<span class="token punctuation">,</span>socket<span class="token punctuation">.</span>SOCK_STREAM<span class="token punctuation">)</span> <span class="token comment">#创建socket对象</span>
<span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'Connecting......'</span><span class="token punctuation">)</span>
client<span class="token punctuation">.</span>connect<span class="token punctuation">(</span><span class="token punctuation">(</span>server_host<span class="token punctuation">,</span>server_port<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">#连接服务端，指定主机和端口</span>
<span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'Connecting is successful!'</span><span class="token punctuation">)</span>

msg <span class="token operator">=</span> client<span class="token punctuation">.</span>recv<span class="token punctuation">(</span>max_recedata<span class="token punctuation">)</span> <span class="token comment">#先接收历史消息</span>
<span class="token keyword">if</span> msg<span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token operator">!=</span><span class="token string">'No message.'</span><span class="token punctuation">:</span>
    <span class="token keyword">print</span><span class="token punctuation">(</span>msg<span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token operator">+</span><span class="token string">'\n------以上是历史消息------\n'</span><span class="token punctuation">)</span>

<span class="token comment">#接收文字的线程</span>
<span class="token comment">#由于用户的发送和接收消息是不同步的，在接收消息时线程会阻塞，所以另开启一个线程进行接收文字</span>
<span class="token keyword">class</span> <span class="token class-name">ThreadReceive</span><span class="token punctuation">(</span>threading<span class="token punctuation">.</span>Thread<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">def</span> <span class="token function">__init__</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span>
        threading<span class="token punctuation">.</span>Thread<span class="token punctuation">.</span>__init__<span class="token punctuation">(</span>self<span class="token punctuation">)</span>
    <span class="token keyword">def</span> <span class="token function">run</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
                receive_msg <span class="token operator">=</span> client<span class="token punctuation">.</span>recv<span class="token punctuation">(</span>max_recedata<span class="token punctuation">)</span>
                <span class="token keyword">print</span><span class="token punctuation">(</span>receive_msg<span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
textThread <span class="token operator">=</span> ThreadReceive<span class="token punctuation">(</span><span class="token punctuation">)</span>
textThread<span class="token punctuation">.</span>start<span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">#发送文字</span>
<span class="token keyword">def</span> <span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
            send_msg <span class="token operator">=</span> <span class="token builtin">input</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
            <span class="token keyword">if</span> send_msg <span class="token operator">==</span> <span class="token string">'0'</span><span class="token punctuation">:</span>
                <span class="token keyword">break</span>
            client<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span>client_name<span class="token operator">+</span><span class="token string">': '</span><span class="token operator">+</span>send_msg<span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
send<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h2 id="初级阶段3：可视化"><a href="#初级阶段3：可视化" class="headerlink" title="初级阶段3：可视化"></a>初级阶段3：可视化</h2><h3 id="代码0-6"><a href="#代码0-6" class="headerlink" title="代码0.6"></a><strong>代码0.6</strong></h3><p><strong>作用：有问题，修理中……主要是服务器老炸了……可能是类的原因</strong></p>
<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment">#服务端</span>
<span class="token comment"># -*- coding:utf-8 -*-</span>
<span class="token keyword">import</span> wx
<span class="token keyword">import</span> socket
<span class="token keyword">import</span> threading


<span class="token keyword">def</span> <span class="token function">getIP</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    s <span class="token operator">=</span> socket<span class="token punctuation">.</span>socket<span class="token punctuation">(</span>socket<span class="token punctuation">.</span>AF_INET<span class="token punctuation">,</span> socket<span class="token punctuation">.</span>SOCK_DGRAM<span class="token punctuation">)</span>
    s<span class="token punctuation">.</span>connect<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">"8.8.8.8"</span><span class="token punctuation">,</span> <span class="token number">80</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    ip<span class="token operator">=</span>s<span class="token punctuation">.</span>getsockname<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span>
    <span class="token keyword">return</span> ip


host <span class="token operator">=</span> getIP<span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token comment"># 获取本地主机名</span>
port <span class="token operator">=</span> <span class="token number">8000</span>  <span class="token comment"># 设置端口</span>
max_connect <span class="token operator">=</span> <span class="token number">2</span>  <span class="token comment"># 设置最大连接客户端数</span>
max_recedata <span class="token operator">=</span> <span class="token number">2048</span>  <span class="token comment"># 设置最大接收字节数</span>
<span class="token keyword">print</span><span class="token punctuation">(</span>host<span class="token punctuation">)</span>

cnt <span class="token operator">=</span> <span class="token number">0</span>  <span class="token comment"># 当前在线人数</span>
textList <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>  <span class="token comment"># 存储历史记录</span>
socketList <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>  <span class="token comment"># 存储已有客户端（套接字）</span>


<span class="token comment"># 自定义类继承，重写run()方法</span>
<span class="token keyword">class</span> <span class="token class-name">ThreadCreate</span><span class="token punctuation">(</span>threading<span class="token punctuation">.</span>Thread<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">def</span> <span class="token function">__init__</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> client<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token comment"># 线程初始化</span>
        threading<span class="token punctuation">.</span>Thread<span class="token punctuation">.</span>__init__<span class="token punctuation">(</span>self<span class="token punctuation">)</span>
        <span class="token comment"># 当作Thread的固定结构吧……</span>
        self<span class="token punctuation">.</span>client <span class="token operator">=</span> client
        <span class="token comment"># 保存嵌套字（客户端）</span>
        socketList<span class="token punctuation">.</span>append<span class="token punctuation">(</span>client<span class="token punctuation">)</span>
        <span class="token comment"># 把嵌套字存在列表里</span>

    <span class="token keyword">def</span> <span class="token function">run</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword">try</span><span class="token punctuation">:</span>
            <span class="token keyword">global</span> cnt
            <span class="token keyword">for</span> sock <span class="token keyword">in</span> socketList<span class="token punctuation">:</span>
                <span class="token keyword">if</span> sock <span class="token operator">==</span> self<span class="token punctuation">.</span>client<span class="token punctuation">:</span>
                    sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'Welcome!There are %d presons.'</span><span class="token operator">%</span><span class="token punctuation">(</span>cnt<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token keyword">else</span><span class="token punctuation">:</span>
                    sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'New Client is Coming.There are %d presons.'</span><span class="token operator">%</span><span class="token punctuation">(</span>cnt<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
            <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
                word <span class="token operator">=</span> self<span class="token punctuation">.</span>client<span class="token punctuation">.</span>recv<span class="token punctuation">(</span>max_recedata<span class="token punctuation">)</span><span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#接收数据</span>
                textList<span class="token punctuation">.</span>append<span class="token punctuation">(</span>word<span class="token punctuation">)</span>
                <span class="token comment"># 生成历史记录</span>
                <span class="token keyword">for</span> sock <span class="token keyword">in</span> socketList<span class="token punctuation">:</span>
                    <span class="token comment"># 给所有客户端发送新消息</span>
                    sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token operator">+</span>word<span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token keyword">except</span> Exception <span class="token keyword">as</span> e<span class="token punctuation">:</span>
            <span class="token comment"># 客户端强制断开连接（关闭窗口）</span>
            <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token builtin">repr</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment"># 如何加一个时间戳？</span>
            cnt <span class="token operator">=</span> cnt<span class="token operator">-</span><span class="token number">1</span>
            <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'Lose one person.There are %d persons.'</span><span class="token operator">%</span><span class="token punctuation">(</span>cnt<span class="token punctuation">)</span><span class="token punctuation">)</span>
            socketList<span class="token punctuation">.</span>remove<span class="token punctuation">(</span>self<span class="token punctuation">.</span>client<span class="token punctuation">)</span> <span class="token comment"># 移除该客户端</span>
            <span class="token keyword">for</span> sock <span class="token keyword">in</span> socketList<span class="token punctuation">:</span>
                sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'Lose one person.There are %d persons.'</span><span class="token operator">%</span><span class="token punctuation">(</span>cnt<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>


<span class="token keyword">class</span> <span class="token class-name">Frame</span><span class="token punctuation">(</span>wx<span class="token punctuation">.</span>Frame<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">def</span> <span class="token function">__init__</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span>
        wx<span class="token punctuation">.</span>Frame<span class="token punctuation">.</span>__init__<span class="token punctuation">(</span>self<span class="token punctuation">,</span> <span class="token boolean">None</span><span class="token punctuation">,</span> title<span class="token operator">=</span><span class="token string">'多人聊天系统（服务器）'</span><span class="token punctuation">,</span> size<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">400</span><span class="token punctuation">,</span> <span class="token number">300</span><span class="token punctuation">)</span><span class="token punctuation">,</span>name<span class="token operator">=</span><span class="token string">'frame'</span><span class="token punctuation">,</span>style<span class="token operator">=</span><span class="token number">541072960</span><span class="token punctuation">)</span>
        self<span class="token punctuation">.</span>qdck <span class="token operator">=</span> wx<span class="token punctuation">.</span>Panel<span class="token punctuation">(</span>self<span class="token punctuation">)</span>
        self<span class="token punctuation">.</span>qdck<span class="token punctuation">.</span>SetOwnBackgroundColour<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token number">255</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        self<span class="token punctuation">.</span>Centre<span class="token punctuation">(</span><span class="token punctuation">)</span>
        self<span class="token punctuation">.</span>an1 <span class="token operator">=</span> wx<span class="token punctuation">.</span>Button<span class="token punctuation">(</span>self<span class="token punctuation">.</span>qdck<span class="token punctuation">,</span>size<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">120</span><span class="token punctuation">,</span> <span class="token number">40</span><span class="token punctuation">)</span><span class="token punctuation">,</span>pos<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">44</span><span class="token punctuation">,</span> <span class="token number">160</span><span class="token punctuation">)</span><span class="token punctuation">,</span>label<span class="token operator">=</span><span class="token string">'启动客户端'</span><span class="token punctuation">,</span>name<span class="token operator">=</span><span class="token string">'button'</span><span class="token punctuation">)</span>
        self<span class="token punctuation">.</span>an1<span class="token punctuation">.</span>SetAuthNeeded<span class="token punctuation">(</span><span class="token boolean">True</span><span class="token punctuation">)</span>
        self<span class="token punctuation">.</span>an1<span class="token punctuation">.</span>Bind<span class="token punctuation">(</span>wx<span class="token punctuation">.</span>EVT_BUTTON<span class="token punctuation">,</span>self<span class="token punctuation">.</span>an1_anbdj<span class="token punctuation">)</span>
        self<span class="token punctuation">.</span>an2 <span class="token operator">=</span> wx<span class="token punctuation">.</span>Button<span class="token punctuation">(</span>self<span class="token punctuation">.</span>qdck<span class="token punctuation">,</span>size<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">120</span><span class="token punctuation">,</span> <span class="token number">40</span><span class="token punctuation">)</span><span class="token punctuation">,</span>pos<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">227</span><span class="token punctuation">,</span> <span class="token number">160</span><span class="token punctuation">)</span><span class="token punctuation">,</span>label<span class="token operator">=</span><span class="token string">'关闭客户端'</span><span class="token punctuation">,</span>name<span class="token operator">=</span><span class="token string">'button'</span><span class="token punctuation">)</span>
        self<span class="token punctuation">.</span>an2<span class="token punctuation">.</span>SetAuthNeeded<span class="token punctuation">(</span><span class="token boolean">True</span><span class="token punctuation">)</span>
        self<span class="token punctuation">.</span>an2<span class="token punctuation">.</span>Bind<span class="token punctuation">(</span>wx<span class="token punctuation">.</span>EVT_BUTTON<span class="token punctuation">,</span>self<span class="token punctuation">.</span>an2_anbdj<span class="token punctuation">)</span>
        self<span class="token punctuation">.</span>bq1 <span class="token operator">=</span> wx<span class="token punctuation">.</span>StaticText<span class="token punctuation">(</span>self<span class="token punctuation">.</span>qdck<span class="token punctuation">,</span>size<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">240</span><span class="token punctuation">,</span> <span class="token number">40</span><span class="token punctuation">)</span><span class="token punctuation">,</span>pos<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">80</span><span class="token punctuation">,</span> <span class="token number">35</span><span class="token punctuation">)</span><span class="token punctuation">,</span>label<span class="token operator">=</span><span class="token string">'多人聊天系统客户端'</span><span class="token punctuation">,</span>name<span class="token operator">=</span><span class="token string">'staticText'</span><span class="token punctuation">,</span>style<span class="token operator">=</span><span class="token number">2321</span><span class="token punctuation">)</span>
        bq1_字体 <span class="token operator">=</span> wx<span class="token punctuation">.</span>Font<span class="token punctuation">(</span><span class="token number">16</span><span class="token punctuation">,</span><span class="token number">70</span><span class="token punctuation">,</span><span class="token number">90</span><span class="token punctuation">,</span><span class="token number">400</span><span class="token punctuation">,</span><span class="token boolean">False</span><span class="token punctuation">,</span><span class="token string">'Microsoft YaHei UI'</span><span class="token punctuation">,</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span>
        self<span class="token punctuation">.</span>bq1<span class="token punctuation">.</span>SetFont<span class="token punctuation">(</span>bq1_字体<span class="token punctuation">)</span>

    <span class="token keyword">def</span> <span class="token function">an1_anbdj</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span>event<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token comment"># print('an1,按钮被单击')</span>
        server <span class="token operator">=</span> socket<span class="token punctuation">.</span>socket<span class="token punctuation">(</span>socket<span class="token punctuation">.</span>AF_INET<span class="token punctuation">,</span> socket<span class="token punctuation">.</span>SOCK_STREAM<span class="token punctuation">)</span>  <span class="token comment"># 创建socket对象</span>
        server<span class="token punctuation">.</span>bind<span class="token punctuation">(</span><span class="token punctuation">(</span>host<span class="token punctuation">,</span> port<span class="token punctuation">)</span><span class="token punctuation">)</span>  <span class="token comment"># 绑定端口号</span>
        server<span class="token punctuation">.</span>listen<span class="token punctuation">(</span>max_connect<span class="token punctuation">)</span>  <span class="token comment"># 开始监听;最大连接2台客户端，超过后排队</span>
        <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'ServerSocket is ready.'</span><span class="token punctuation">)</span>
        <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
            client<span class="token punctuation">,</span> addr <span class="token operator">=</span> server<span class="token punctuation">.</span>accept<span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token comment"># 创建客户端连接，每次接收一个连接</span>
            <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">"连接地址：%s"</span> <span class="token operator">%</span> <span class="token builtin">str</span><span class="token punctuation">(</span>addr<span class="token punctuation">)</span><span class="token punctuation">)</span>
            <span class="token keyword">try</span><span class="token punctuation">:</span>
                <span class="token keyword">global</span> cnt
                <span class="token comment"># 关于历史记录的处理</span>
                <span class="token keyword">if</span> <span class="token builtin">len</span><span class="token punctuation">(</span>textList<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">:</span>
                    client<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token string">'No message.'</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token keyword">else</span><span class="token punctuation">:</span>
                    client<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">.</span>join<span class="token punctuation">(</span>textList<span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

                cnt <span class="token operator">=</span> cnt <span class="token operator">+</span> <span class="token number">1</span>  <span class="token comment"># 来了一个人加一</span>

                <span class="token comment"># 给用户创建新进程</span>
                newThread <span class="token operator">=</span> ThreadCreate<span class="token punctuation">(</span>client<span class="token punctuation">)</span>
                newThread<span class="token punctuation">.</span>setDaemon<span class="token punctuation">(</span><span class="token boolean">True</span><span class="token punctuation">)</span>  <span class="token comment"># 设置为守护线程</span>
                newThread<span class="token punctuation">.</span>start<span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token comment"># 开启线程</span>

                <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'Connecting is successful!The number of people is '</span> <span class="token operator">+</span> <span class="token builtin">str</span><span class="token punctuation">(</span>cnt<span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token string">'.'</span><span class="token punctuation">)</span>
            <span class="token keyword">except</span> Exception <span class="token keyword">as</span> e<span class="token punctuation">:</span>
                <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token builtin">repr</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">)</span>

    <span class="token keyword">def</span> <span class="token function">an2_anbdj</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span>event<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'an2,按钮被单击'</span><span class="token punctuation">)</span>


<span class="token keyword">class</span> <span class="token class-name">myApp</span><span class="token punctuation">(</span>wx<span class="token punctuation">.</span>App<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">def</span> <span class="token function">OnInit</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span>
        self<span class="token punctuation">.</span>frame <span class="token operator">=</span> Frame<span class="token punctuation">(</span><span class="token punctuation">)</span>
        self<span class="token punctuation">.</span>frame<span class="token punctuation">.</span>Show<span class="token punctuation">(</span><span class="token boolean">True</span><span class="token punctuation">)</span>
        <span class="token keyword">return</span> <span class="token boolean">True</span>


<span class="token keyword">if</span> __name__ <span class="token operator">==</span> <span class="token string">'__main__'</span><span class="token punctuation">:</span>
    app <span class="token operator">=</span> myApp<span class="token punctuation">(</span><span class="token punctuation">)</span>
    app<span class="token punctuation">.</span>MainLoop<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<pre class="line-numbers language-py" data-language="py"><code class="language-py"><span class="token comment"># coding=utf-8</span>
<span class="token keyword">import</span> wx
<span class="token keyword">import</span> socket
<span class="token keyword">import</span> threading
<span class="token keyword">from</span> time <span class="token keyword">import</span> sleep<span class="token punctuation">,</span> localtime
<span class="token keyword">from</span> datetime <span class="token keyword">import</span> datetime

server_host <span class="token operator">=</span> socket<span class="token punctuation">.</span>gethostname<span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment"># 获取本地主机名</span>
server_port <span class="token operator">=</span> <span class="token number">8000</span>
<span class="token comment"># 设置端口</span>
max_recedata <span class="token operator">=</span> <span class="token number">2048</span>
<span class="token comment"># 设置最大接收字节数</span>
client_name <span class="token operator">=</span> socket<span class="token punctuation">.</span>gethostname<span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">print</span><span class="token punctuation">(</span>server_host<span class="token punctuation">)</span>
lock <span class="token operator">=</span> threading<span class="token punctuation">.</span>Lock<span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment"># 创建锁</span>
host_ip <span class="token operator">=</span> <span class="token string">''</span>
client <span class="token operator">=</span> socket<span class="token punctuation">.</span>socket<span class="token punctuation">(</span>socket<span class="token punctuation">.</span>AF_INET<span class="token punctuation">,</span> socket<span class="token punctuation">.</span>SOCK_STREAM<span class="token punctuation">)</span>  <span class="token comment"># 创建socket对象</span>



<span class="token keyword">class</span> <span class="token class-name">chuangkou</span><span class="token punctuation">(</span>wx<span class="token punctuation">.</span>Frame<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">def</span> <span class="token function">__init__</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span>
        self<span class="token punctuation">.</span>liaotian <span class="token operator">=</span> <span class="token number">0</span>
        <span class="token comment"># 判断是否取过消息记录</span>
        <span class="token builtin">super</span><span class="token punctuation">(</span>chuangkou<span class="token punctuation">,</span> self<span class="token punctuation">)</span><span class="token punctuation">.</span>__init__<span class="token punctuation">(</span><span class="token boolean">None</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> title<span class="token operator">=</span><span class="token string">"多人聊天程序"</span><span class="token punctuation">,</span> size<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">600</span><span class="token punctuation">,</span> <span class="token number">600</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        self<span class="token punctuation">.</span>a <span class="token operator">=</span> wx<span class="token punctuation">.</span>Panel<span class="token punctuation">(</span>self<span class="token punctuation">)</span>
        <span class="token comment"># 创建一个画板</span>
        self<span class="token punctuation">.</span>ip<span class="token operator">=</span>wx<span class="token punctuation">.</span>TextCtrl<span class="token punctuation">(</span>self<span class="token punctuation">.</span>a<span class="token punctuation">,</span>style<span class="token operator">=</span>wx<span class="token punctuation">.</span>TE_PROCESS_ENTER <span class="token punctuation">,</span>value<span class="token operator">=</span><span class="token string">"请输入服务器的ip地址"</span><span class="token punctuation">)</span>
        <span class="token comment"># 创建一个输入服务器ip地址的输入框</span>
        self<span class="token punctuation">.</span>b <span class="token operator">=</span> wx<span class="token punctuation">.</span>Button<span class="token punctuation">(</span>self<span class="token punctuation">.</span>a<span class="token punctuation">,</span> wx<span class="token punctuation">.</span>ID_ANY<span class="token punctuation">,</span> <span class="token string">"确定"</span><span class="token punctuation">)</span>
        self<span class="token punctuation">.</span>b<span class="token punctuation">.</span>SetAuthNeeded<span class="token punctuation">(</span><span class="token boolean">True</span><span class="token punctuation">)</span>
        self<span class="token punctuation">.</span>b<span class="token punctuation">.</span>Bind<span class="token punctuation">(</span>wx<span class="token punctuation">.</span>EVT_BUTTON<span class="token punctuation">,</span> self<span class="token punctuation">.</span>b_anbdj<span class="token punctuation">)</span>
        <span class="token comment"># 创建一个聊天创建的输入框</span>
        self<span class="token punctuation">.</span>text <span class="token operator">=</span> wx<span class="token punctuation">.</span>TextCtrl<span class="token punctuation">(</span>self<span class="token punctuation">.</span>a<span class="token punctuation">,</span>
                             style<span class="token operator">=</span>wx<span class="token punctuation">.</span>TE_READONLY <span class="token operator">|</span> wx<span class="token punctuation">.</span>TE_MULTILINE <span class="token operator">|</span> wx<span class="token punctuation">.</span>TE_RICH2 <span class="token operator">|</span> wx<span class="token punctuation">.</span>BORDER_SIMPLE <span class="token operator">|</span> wx<span class="token punctuation">.</span>HSCROLL<span class="token punctuation">)</span>
        self<span class="token punctuation">.</span>text<span class="token punctuation">.</span>SetBackgroundColour<span class="token punctuation">(</span><span class="token string">'#d1d1d1'</span><span class="token punctuation">)</span>  <span class="token comment"># 颜色改变为灰</span>
        self<span class="token punctuation">.</span>ctrl <span class="token operator">=</span> wx<span class="token punctuation">.</span>TextCtrl<span class="token punctuation">(</span>self<span class="token punctuation">.</span>a<span class="token punctuation">,</span> style<span class="token operator">=</span>wx<span class="token punctuation">.</span>TE_PROCESS_ENTER <span class="token operator">|</span> wx<span class="token punctuation">.</span>TE_MULTILINE<span class="token punctuation">,</span>value<span class="token operator">=</span><span class="token string">""</span><span class="token punctuation">)</span>
        <span class="token comment"># 创建一个输入发送聊天内容的输入框</span>
        self<span class="token punctuation">.</span>sent <span class="token operator">=</span> wx<span class="token punctuation">.</span>Button<span class="token punctuation">(</span>self<span class="token punctuation">.</span>a<span class="token punctuation">,</span> wx<span class="token punctuation">.</span>ID_ANY<span class="token punctuation">,</span> <span class="token string">"发送"</span><span class="token punctuation">)</span>
        self<span class="token punctuation">.</span>sent<span class="token punctuation">.</span>SetAuthNeeded<span class="token punctuation">(</span><span class="token boolean">True</span><span class="token punctuation">)</span>
        self<span class="token punctuation">.</span>sent<span class="token punctuation">.</span>Bind<span class="token punctuation">(</span>wx<span class="token punctuation">.</span>EVT_BUTTON<span class="token punctuation">,</span> self<span class="token punctuation">.</span>sent_anbdj<span class="token punctuation">)</span>
        box <span class="token operator">=</span> wx<span class="token punctuation">.</span>BoxSizer<span class="token punctuation">(</span>wx<span class="token punctuation">.</span>HORIZONTAL<span class="token punctuation">)</span>  <span class="token comment"># 创建一个垂直布局</span>
        box1 <span class="token operator">=</span> wx<span class="token punctuation">.</span>BoxSizer<span class="token punctuation">(</span>wx<span class="token punctuation">.</span>VERTICAL<span class="token punctuation">)</span>  <span class="token comment"># 创建一个平行布局</span>
        box1<span class="token punctuation">.</span>Add<span class="token punctuation">(</span>self<span class="token punctuation">.</span>ip<span class="token punctuation">,</span>proportion<span class="token operator">=</span><span class="token number">3</span><span class="token punctuation">,</span> flag<span class="token operator">=</span>wx<span class="token punctuation">.</span>EXPAND<span class="token operator">|</span>wx<span class="token punctuation">.</span>TOP<span class="token punctuation">,</span>border<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">)</span>
        <span class="token comment"># 输入ip地址的输入框的布局</span>
        box1<span class="token punctuation">.</span>Add<span class="token punctuation">(</span>self<span class="token punctuation">.</span>b<span class="token punctuation">,</span> proportion<span class="token operator">=</span><span class="token number">1</span><span class="token punctuation">,</span> flag<span class="token operator">=</span>wx<span class="token punctuation">.</span>EXPAND <span class="token operator">|</span> wx<span class="token punctuation">.</span>TOP<span class="token punctuation">,</span> border<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">)</span>
        <span class="token comment"># 查看聊天记录按钮的布局</span>
        box1<span class="token punctuation">.</span>Add<span class="token punctuation">(</span>self<span class="token punctuation">.</span>text<span class="token punctuation">,</span> proportion<span class="token operator">=</span><span class="token number">30</span><span class="token punctuation">,</span> flag<span class="token operator">=</span>wx<span class="token punctuation">.</span>EXPAND <span class="token operator">|</span> wx<span class="token punctuation">.</span>TOP<span class="token punctuation">,</span> border<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">)</span>
        <span class="token comment"># 接收输入框的布局</span>
        box1<span class="token punctuation">.</span>Add<span class="token punctuation">(</span>self<span class="token punctuation">.</span>ctrl<span class="token punctuation">,</span> proportion<span class="token operator">=</span><span class="token number">20</span><span class="token punctuation">,</span> flag<span class="token operator">=</span>wx<span class="token punctuation">.</span>EXPAND <span class="token operator">|</span> wx<span class="token punctuation">.</span>TOP<span class="token punctuation">,</span> border<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">)</span>
        <span class="token comment"># 发送的输入框的布局</span>
        box1<span class="token punctuation">.</span>Add<span class="token punctuation">(</span>self<span class="token punctuation">.</span>sent<span class="token punctuation">,</span> proportion<span class="token operator">=</span><span class="token number">3</span><span class="token punctuation">,</span> flag<span class="token operator">=</span>wx<span class="token punctuation">.</span>EXPAND <span class="token operator">|</span> wx<span class="token punctuation">.</span>TOP<span class="token punctuation">,</span> border<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">)</span>
        self<span class="token punctuation">.</span>a<span class="token punctuation">.</span>SetSizer<span class="token punctuation">(</span>box1<span class="token punctuation">)</span>  <span class="token comment"># 布局设置在a画板上</span>
        self<span class="token punctuation">.</span>msg<span class="token operator">=</span><span class="token string">''</span>

    <span class="token keyword">def</span> <span class="token function">b_anbdj</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span>event<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword">global</span> msg
        host_ip<span class="token operator">=</span>self<span class="token punctuation">.</span>ip<span class="token punctuation">.</span>GetValue<span class="token punctuation">(</span><span class="token punctuation">)</span>
        toastone <span class="token operator">=</span> wx<span class="token punctuation">.</span>MessageDialog<span class="token punctuation">(</span><span class="token boolean">None</span><span class="token punctuation">,</span> <span class="token string">"链接的服务器地址为"</span><span class="token operator">+</span>host_ip<span class="token punctuation">,</span> <span class="token string">"信息提示"</span><span class="token punctuation">,</span> wx<span class="token punctuation">.</span>YES_DEFAULT <span class="token operator">|</span> wx<span class="token punctuation">.</span>ICON_QUESTION<span class="token punctuation">)</span>
        <span class="token keyword">if</span> toastone<span class="token punctuation">.</span>ShowModal<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">==</span> wx<span class="token punctuation">.</span>ID_YES<span class="token punctuation">:</span>
            <span class="token comment"># 如果点击了提示框的确定按钮</span>
            toastone<span class="token punctuation">.</span>Destroy<span class="token punctuation">(</span><span class="token punctuation">)</span>
            <span class="token comment"># 则关闭提示框</span>
        client<span class="token punctuation">.</span>connect<span class="token punctuation">(</span><span class="token punctuation">(</span>host_ip<span class="token punctuation">,</span> server_port<span class="token punctuation">)</span><span class="token punctuation">)</span>  <span class="token comment"># 连接服务端，指定主机和端口</span>
        toastone <span class="token operator">=</span> wx<span class="token punctuation">.</span>MessageDialog<span class="token punctuation">(</span><span class="token boolean">None</span><span class="token punctuation">,</span> <span class="token string">"Connecting is successful!"</span><span class="token punctuation">,</span> <span class="token string">"信息提示"</span><span class="token punctuation">,</span> wx<span class="token punctuation">.</span>YES_DEFAULT <span class="token operator">|</span> wx<span class="token punctuation">.</span>ICON_QUESTION<span class="token punctuation">)</span>
        <span class="token keyword">if</span> toastone<span class="token punctuation">.</span>ShowModal<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">==</span> wx<span class="token punctuation">.</span>ID_YES<span class="token punctuation">:</span>
            <span class="token comment"># 如果点击了提示框的确定按钮</span>
            toastone<span class="token punctuation">.</span>Destroy<span class="token punctuation">(</span><span class="token punctuation">)</span>
            <span class="token comment"># 则关闭提示框</span>

    <span class="token keyword">def</span> <span class="token function">sent_anbdj</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span>event<span class="token punctuation">)</span><span class="token punctuation">:</span>
        send_msg <span class="token operator">=</span> self<span class="token punctuation">.</span>ctrl<span class="token punctuation">.</span>GetValue<span class="token punctuation">(</span><span class="token punctuation">)</span>
        client<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span>client_name <span class="token operator">+</span> <span class="token string">': '</span> <span class="token operator">+</span> send_msg<span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

    <span class="token comment"># 接收文字的线程</span>
    <span class="token comment"># 由于用户的发送和接收消息是不同步的，在接收消息时线程会阻塞，所以另开启一个线程进行接收文字</span>
    <span class="token keyword">def</span> <span class="token function">ThreadReceive</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
            self<span class="token punctuation">.</span>msg <span class="token operator">=</span> client<span class="token punctuation">.</span>recv<span class="token punctuation">(</span>max_recedata<span class="token punctuation">)</span>
            self<span class="token punctuation">.</span>text<span class="token punctuation">.</span>AppendText<span class="token punctuation">(</span>self<span class="token punctuation">.</span>msg<span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token string">"\n\n"</span><span class="token punctuation">)</span>


<span class="token keyword">if</span> __name__ <span class="token operator">==</span> <span class="token string">'__main__'</span><span class="token punctuation">:</span>
    app <span class="token operator">=</span> wx<span class="token punctuation">.</span>App<span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token comment"># 初始化</span>
    shili <span class="token operator">=</span> chuangkou<span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token comment"># 创建实例</span>
    shili<span class="token punctuation">.</span>Show<span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token comment"># 显示窗口</span>
    app<span class="token punctuation">.</span>MainLoop<span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token comment"># 窗口主循环</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h2 id="初级阶段4：线程改版-tkinter使用"><a href="#初级阶段4：线程改版-tkinter使用" class="headerlink" title="初级阶段4：线程改版+tkinter使用"></a>初级阶段4：线程改版+tkinter使用</h2><h3 id="0-5"><a href="#0-5" class="headerlink" title="0.5"></a><strong>0.5</strong></h3><p><strong>作用:换了个线程控制方式</strong></p>
<blockquote>
<p>变化：</p>
<pre class="line-numbers language-none"><code class="language-none">server.listen() #监听
server &#x3D; socket.socket() #创建server对象<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre>
</blockquote>
<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment">#服务器端</span>
<span class="token keyword">import</span> socket
<span class="token keyword">import</span> threading


host <span class="token operator">=</span> socket<span class="token punctuation">.</span>gethostname<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#获取当前主机的IP地址</span>
port <span class="token operator">=</span> <span class="token number">8000</span> <span class="token comment">#设置防火墙开放端口</span>
SocketList <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token comment">#存储客户端套接字的列表</span>
TextList <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token comment">#存储聊天记录</span>
cnt <span class="token operator">=</span> <span class="token number">0</span> <span class="token comment">#当前客户端人数</span>
<span class="token keyword">print</span><span class="token punctuation">(</span>host<span class="token punctuation">)</span>

server <span class="token operator">=</span> socket<span class="token punctuation">.</span>socket<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#创建server对象</span>
server<span class="token punctuation">.</span>bind<span class="token punctuation">(</span><span class="token punctuation">(</span>host<span class="token punctuation">,</span>port<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">#绑定</span>
server<span class="token punctuation">.</span>listen<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#监听</span>
<span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'服务器准备就绪！'</span><span class="token punctuation">)</span>

<span class="token comment">#接收一个客户端连接，及其发送来数据</span>
<span class="token keyword">def</span> <span class="token function">read_client</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">try</span><span class="token punctuation">:</span>
        <span class="token comment">#接受客户端发送来的数据</span>
        <span class="token keyword">return</span> s<span class="token punctuation">.</span>recv<span class="token punctuation">(</span><span class="token number">2048</span><span class="token punctuation">)</span><span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span>
    <span class="token keyword">except</span><span class="token punctuation">:</span>
        <span class="token comment">#客户端异常，连接失败，则删除该socket</span>
        <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token builtin">str</span><span class="token punctuation">(</span>addr<span class="token punctuation">)</span><span class="token operator">+</span><span class="token string">'已下线！'</span><span class="token punctuation">)</span>
        SocketList<span class="token punctuation">.</span>remove<span class="token punctuation">(</span>s<span class="token punctuation">)</span>

<span class="token comment">#多线程：将收到的消息发送给所有客户端</span>
<span class="token keyword">def</span> <span class="token function">send_client</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">try</span><span class="token punctuation">:</span>
        <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
            content <span class="token operator">=</span> read_client<span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token comment">#客户端消息</span>
            <span class="token keyword">if</span> content <span class="token keyword">is</span> <span class="token boolean">None</span><span class="token punctuation">:</span> <span class="token comment">#如果没有结束循环</span>
                <span class="token keyword">break</span>
            <span class="token keyword">else</span><span class="token punctuation">:</span> <span class="token comment">#如果有将消息保存到历史记录</span>
                TextList<span class="token punctuation">.</span>append<span class="token punctuation">(</span><span class="token builtin">str</span><span class="token punctuation">(</span>addr<span class="token punctuation">)</span><span class="token operator">+</span><span class="token string">': '</span><span class="token operator">+</span>content<span class="token punctuation">)</span>
            <span class="token comment">#将一个客户端发送过来的数据广播给其他客户端</span>
            <span class="token keyword">for</span> sock <span class="token keyword">in</span> SocketList<span class="token punctuation">:</span>
                sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token builtin">str</span><span class="token punctuation">(</span>addr<span class="token punctuation">)</span><span class="token operator">+</span><span class="token string">': '</span><span class="token operator">+</span>content<span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">except</span><span class="token punctuation">:</span>
        <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'广播未成功！'</span><span class="token punctuation">)</span>

<span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
    client<span class="token punctuation">,</span>addr <span class="token operator">=</span> server<span class="token punctuation">.</span>accept<span class="token punctuation">(</span><span class="token punctuation">)</span>
    SocketList<span class="token punctuation">.</span>append<span class="token punctuation">(</span>client<span class="token punctuation">)</span>
    <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token builtin">str</span><span class="token punctuation">(</span>addr<span class="token punctuation">)</span><span class="token operator">+</span><span class="token string">'已加入！'</span><span class="token punctuation">)</span>

    <span class="token keyword">try</span><span class="token punctuation">:</span>
        <span class="token comment">#历史消息生成</span>
        <span class="token keyword">if</span> <span class="token builtin">len</span><span class="token punctuation">(</span>TextList<span class="token punctuation">)</span><span class="token operator">==</span><span class="token number">0</span><span class="token punctuation">:</span>
            client<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token string">'No message.'</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token keyword">else</span><span class="token punctuation">:</span>
            client<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">.</span>join<span class="token punctuation">(</span>TextList<span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

        cnt <span class="token operator">=</span> cnt <span class="token operator">+</span> <span class="token number">1</span>

        <span class="token comment">#每当有客户连接后，就启动一个线程为其服务</span>
        threading<span class="token punctuation">.</span>Thread<span class="token punctuation">(</span>target<span class="token operator">=</span>send_client<span class="token punctuation">,</span> args<span class="token operator">=</span><span class="token punctuation">(</span>client<span class="token punctuation">,</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>start<span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">except</span> Exception <span class="token keyword">as</span> e<span class="token punctuation">:</span>
        <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token builtin">repr</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<pre class="line-numbers language-py" data-language="py"><code class="language-py"><span class="token comment">#客户端</span>
<span class="token keyword">import</span> socket
<span class="token keyword">import</span> threading

server_host <span class="token operator">=</span> socket<span class="token punctuation">.</span>gethostname<span class="token punctuation">(</span><span class="token punctuation">)</span>
server_port <span class="token operator">=</span> <span class="token number">8000</span>

client <span class="token operator">=</span> socket<span class="token punctuation">.</span>socket<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#创建socket对象</span>
<span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'Connecting......'</span><span class="token punctuation">)</span>
client<span class="token punctuation">.</span>connect<span class="token punctuation">(</span><span class="token punctuation">(</span>server_host<span class="token punctuation">,</span>server_port<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">#连接服务端，指定主机和端口</span>
<span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'Connecting is successful!'</span><span class="token punctuation">)</span>

content <span class="token operator">=</span> client<span class="token punctuation">.</span>recv<span class="token punctuation">(</span><span class="token number">2048</span><span class="token punctuation">)</span><span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span>
<span class="token keyword">if</span> content <span class="token operator">!=</span> <span class="token string">'No message.'</span><span class="token punctuation">:</span>
    <span class="token keyword">print</span><span class="token punctuation">(</span>content <span class="token operator">+</span> <span class="token string">'\n------以上是历史消息------\n'</span><span class="token punctuation">)</span>

<span class="token keyword">def</span> <span class="token function">read_server</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
        <span class="token comment">#子线程负责从服务端接受数据并打印</span>
        content <span class="token operator">=</span> c<span class="token punctuation">.</span>recv<span class="token punctuation">(</span><span class="token number">2048</span><span class="token punctuation">)</span><span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span>
        <span class="token keyword">print</span><span class="token punctuation">(</span>content<span class="token punctuation">)</span>
threading<span class="token punctuation">.</span>Thread<span class="token punctuation">(</span>target<span class="token operator">=</span>read_server<span class="token punctuation">,</span> args<span class="token operator">=</span><span class="token punctuation">(</span>client<span class="token punctuation">,</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>start<span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
    word <span class="token operator">=</span> <span class="token builtin">input</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">if</span> word <span class="token operator">==</span> <span class="token string">'close'</span><span class="token punctuation">:</span>
        <span class="token keyword">break</span>
    <span class="token comment"># 主线程负责将用户输入的数据发送到socket中</span>
    client<span class="token punctuation">.</span>send<span class="token punctuation">(</span>word<span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h3 id="0-6"><a href="#0-6" class="headerlink" title="0.6"></a><strong>0.6</strong></h3><p><strong>作用：0.5基础上优化（nickname）+进行图形界面可视化；</strong></p>
<blockquote>
<p>Python 提供了多个图形开发界面的库，几个常用 Python GUI 库如下：</p>
<ul>
<li><strong>Tkinter：</strong> Tkinter 模块(Tk 接口)是 Python 的标准 Tk GUI 工具包的接口 .Tk 和 Tkinter 可以在大多数的 Unix 平台下使用,同样可以应用在 Windows 和 Macintosh 系统里。Tk8.0 的后续版本可以实现本地窗口风格,并良好地运行在绝大多数平台中。</li>
</ul>
<p><strong>注意</strong><em>：Python3.x 版本使用的库名为 tkinter,即首写字母 T 为小写</em></p>
<p>创建一个GUI程序</p>
<ul>
<li>1、导入 Tkinter 模块</li>
<li>2、创建控件</li>
<li>3、指定这个控件的 master， 即这个控件属于哪一个</li>
<li>4、告诉 GM(geometry manager) 有一个控件产生了。</li>
</ul>
</blockquote>
<blockquote>
<p>[Python GUI 编程(Tkinter) | 菜鸟教程 (runoob.com)](<a target="_blank" rel="noopener" href="https://www.runoob.com/python/python-gui-tkinter.html#:~:text=Tkinter">https://www.runoob.com/python/python-gui-tkinter.html#:~:text=Tkinter</a> 是 Python 的标准 GUI 库。 Python 使用,Tkinter 库、而且 IDLE 也是用 Tkinter 编写而成、对于简单的图形界面 Tkinter 还是能应付自如。)</p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/Eider1998/article/details/104725180">(29条消息) TK-StringVar_Eider1998的博客-CSDN博客_stringvar()作用</a></p>
<p><a target="_blank" rel="noopener" href="https://www.runoob.com/python/python-tk-frame.html">Python Tkinter 框架控件（Frame） | 菜鸟教程 (runoob.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/Bugest/article/details/81557112">(29条消息) python弹窗——tkinter.messagebox学习总结_鹿鹿有为啊的博客-CSDN博客_python tkinter 弹窗</a></p>
<p><a target="_blank" rel="noopener" href="https://www.cnblogs.com/zmzzm/p/11973217.html">tkinter的set()与get() - 做梦者造梦 - 博客园 (cnblogs.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_46018418/article/details/105927203">(29条消息) tkinter库最全使用教程_千禧皓月的博客-CSDN博客_tkinter</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/superfanstoprogram/article/details/83713196">(29条消息) 用tkinter.pack设计复杂界面布局_快乐清风客的博客-CSDN博客_tkinter复杂界面</a></p>
</blockquote>
<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment">#服务端</span>
<span class="token keyword">import</span> socket
<span class="token keyword">import</span> threading


host <span class="token operator">=</span> socket<span class="token punctuation">.</span>gethostname<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#获取当前主机的IP地址</span>
port <span class="token operator">=</span> <span class="token number">8000</span> <span class="token comment">#设置防火墙开放端口</span>
SocketList <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token comment">#存储客户端套接字的列表</span>
TextList <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token comment">#存储聊天记录</span>
Nickname <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token comment">#存储用户呢称</span>
cnt <span class="token operator">=</span> <span class="token number">0</span> <span class="token comment">#当前客户端人数</span>
<span class="token keyword">print</span><span class="token punctuation">(</span>host<span class="token punctuation">)</span>

server <span class="token operator">=</span> socket<span class="token punctuation">.</span>socket<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#创建server对象</span>
server<span class="token punctuation">.</span>bind<span class="token punctuation">(</span><span class="token punctuation">(</span>host<span class="token punctuation">,</span>port<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">#绑定</span>
server<span class="token punctuation">.</span>listen<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#监听</span>
<span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'服务器准备就绪！'</span><span class="token punctuation">)</span>

<span class="token comment">#接收一个客户端连接，及其发送来数据</span>
<span class="token keyword">def</span> <span class="token function">read_client</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span>nickname<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">try</span><span class="token punctuation">:</span>
        <span class="token comment">#接受客户端发送来的数据</span>
        <span class="token keyword">return</span> s<span class="token punctuation">.</span>recv<span class="token punctuation">(</span><span class="token number">2048</span><span class="token punctuation">)</span><span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span>
    <span class="token keyword">except</span><span class="token punctuation">:</span>
        <span class="token comment">#客户端异常，连接失败，则删除该socket</span>
        <span class="token comment"># print(str(addr)+'已下线！')</span>
        <span class="token keyword">print</span><span class="token punctuation">(</span>nickname <span class="token operator">+</span> <span class="token string">'已下线！'</span><span class="token punctuation">)</span>
        SocketList<span class="token punctuation">.</span>remove<span class="token punctuation">(</span>s<span class="token punctuation">)</span>
        Nickname<span class="token punctuation">.</span>remove<span class="token punctuation">(</span>nickname<span class="token punctuation">)</span>
        <span class="token keyword">for</span> sock <span class="token keyword">in</span> SocketList<span class="token punctuation">:</span>
            sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'系统消息：'</span> <span class="token operator">+</span> nickname <span class="token operator">+</span> <span class="token string">'已下线！'</span><span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">#多线程：将收到的消息发送给所有客户端</span>
<span class="token keyword">def</span> <span class="token function">send_client</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span>nickname<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">try</span><span class="token punctuation">:</span>
        s<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">','</span><span class="token punctuation">.</span>join<span class="token punctuation">(</span>Nickname<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">#将用户列表发送给各客户端</span>
        <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
            content <span class="token operator">=</span> read_client<span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token comment">#客户端消息</span>
            <span class="token keyword">if</span> content <span class="token keyword">is</span> <span class="token boolean">None</span><span class="token punctuation">:</span> <span class="token comment">#如果没有结束循环</span>
                <span class="token keyword">break</span>
            <span class="token keyword">else</span><span class="token punctuation">:</span> <span class="token comment">#如果有将消息保存到历史记录</span>
                <span class="token comment"># TextList.append(str(addr)+': '+content)</span>
                TextList<span class="token punctuation">.</span>append<span class="token punctuation">(</span>nickname <span class="token operator">+</span> <span class="token string">': '</span> <span class="token operator">+</span> content<span class="token punctuation">)</span>
            <span class="token comment">#将一个客户端发送过来的数据广播给其他客户端</span>
            <span class="token keyword">for</span> sock <span class="token keyword">in</span> SocketList<span class="token punctuation">:</span>
                <span class="token comment"># sock.send((str(addr)+': '+content).encode('utf-8'))</span>
                sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span>nickname <span class="token operator">+</span> <span class="token string">': '</span> <span class="token operator">+</span> content<span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">except</span><span class="token punctuation">:</span>
        <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'广播未成功！'</span><span class="token punctuation">)</span>

<span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
    client<span class="token punctuation">,</span>addr <span class="token operator">=</span> server<span class="token punctuation">.</span>accept<span class="token punctuation">(</span><span class="token punctuation">)</span>
    SocketList<span class="token punctuation">.</span>append<span class="token punctuation">(</span>client<span class="token punctuation">)</span>

    <span class="token keyword">try</span><span class="token punctuation">:</span>
        nickname <span class="token operator">=</span> client<span class="token punctuation">.</span>recv<span class="token punctuation">(</span><span class="token number">2048</span><span class="token punctuation">)</span><span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span>
        <span class="token comment"># print(str(addr)+'已加入！')</span>

        <span class="token keyword">if</span> nickname <span class="token keyword">in</span> Nickname<span class="token punctuation">:</span>
            i <span class="token operator">=</span> <span class="token number">1</span>
            <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
                <span class="token keyword">if</span> nickname<span class="token operator">+</span><span class="token builtin">str</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span> <span class="token keyword">in</span> Nickname<span class="token punctuation">:</span>
                    i <span class="token operator">=</span> i<span class="token operator">+</span><span class="token number">1</span>
                <span class="token keyword">else</span><span class="token punctuation">:</span>
                    nickname <span class="token operator">=</span> nickname <span class="token operator">+</span> <span class="token builtin">str</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span>
                    <span class="token keyword">break</span>
        Nickname<span class="token punctuation">.</span>append<span class="token punctuation">(</span>nickname<span class="token punctuation">)</span>
        <span class="token keyword">print</span><span class="token punctuation">(</span>nickname <span class="token operator">+</span> <span class="token string">'已加入！'</span><span class="token punctuation">)</span>
        <span class="token keyword">for</span> sock <span class="token keyword">in</span> SocketList<span class="token punctuation">:</span>
            sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'系统消息：'</span> <span class="token operator">+</span> nickname <span class="token operator">+</span> <span class="token string">'已加入！'</span><span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

        <span class="token comment">#历史消息生成</span>
        <span class="token keyword">if</span> <span class="token builtin">len</span><span class="token punctuation">(</span>TextList<span class="token punctuation">)</span><span class="token operator">==</span><span class="token number">0</span><span class="token punctuation">:</span>
            client<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token string">'No message.'</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token keyword">else</span><span class="token punctuation">:</span>
            client<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">.</span>join<span class="token punctuation">(</span>TextList<span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

        cnt <span class="token operator">=</span> cnt <span class="token operator">+</span> <span class="token number">1</span>

        <span class="token comment">#每当有客户连接后，就启动一个线程为其服务</span>
        <span class="token comment">#加入线程中跑，加入函数为send_client，参数为client,nickname</span>
        threading<span class="token punctuation">.</span>Thread<span class="token punctuation">(</span>target<span class="token operator">=</span>send_client<span class="token punctuation">,</span> args<span class="token operator">=</span><span class="token punctuation">(</span>client<span class="token punctuation">,</span>nickname<span class="token punctuation">,</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>start<span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">except</span> Exception <span class="token keyword">as</span> e<span class="token punctuation">:</span>
        <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token builtin">repr</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h3 id="0-65"><a href="#0-65" class="headerlink" title="0.65"></a><strong>0.65</strong></h3><p><strong>作用：0.6基础上的修改（显示在线人数和历史消息暂时删了，仅保留了聊天功能），先能用……还要解决子线程如何关闭的问题……</strong></p>
<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment">#服务端</span>
<span class="token keyword">import</span> socket
<span class="token keyword">import</span> threading


host <span class="token operator">=</span> socket<span class="token punctuation">.</span>gethostname<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#获取当前主机的IP地址</span>
port <span class="token operator">=</span> <span class="token number">9999</span> <span class="token comment">#设置防火墙开放端口</span>
SocketList <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token comment">#存储客户端套接字的列表</span>
TextList <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token comment">#存储聊天记录</span>
Nickname <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token comment">#存储用户呢称</span>
cnt <span class="token operator">=</span> <span class="token number">0</span> <span class="token comment">#当前客户端人数</span>
<span class="token keyword">print</span><span class="token punctuation">(</span>host<span class="token punctuation">)</span>

server <span class="token operator">=</span> socket<span class="token punctuation">.</span>socket<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#创建server对象</span>
server<span class="token punctuation">.</span>bind<span class="token punctuation">(</span><span class="token punctuation">(</span>host<span class="token punctuation">,</span>port<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">#绑定</span>
server<span class="token punctuation">.</span>listen<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#监听</span>
<span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'服务器准备就绪！'</span><span class="token punctuation">)</span>

<span class="token comment">#接收一个客户端连接，及其发送来数据</span>
<span class="token keyword">def</span> <span class="token function">read_client</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span>nickname<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">try</span><span class="token punctuation">:</span>
        <span class="token comment">#接受客户端发送来的数据</span>
        <span class="token keyword">return</span> s<span class="token punctuation">.</span>recv<span class="token punctuation">(</span><span class="token number">2048</span><span class="token punctuation">)</span><span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span>
    <span class="token keyword">except</span><span class="token punctuation">:</span>
        <span class="token comment">#客户端异常，连接失败，则删除该socket</span>
        <span class="token comment"># print(str(addr)+'已下线！')</span>
        <span class="token keyword">print</span><span class="token punctuation">(</span>nickname <span class="token operator">+</span> <span class="token string">'已下线！'</span><span class="token punctuation">)</span>
        SocketList<span class="token punctuation">.</span>remove<span class="token punctuation">(</span>s<span class="token punctuation">)</span>
        Nickname<span class="token punctuation">.</span>remove<span class="token punctuation">(</span>nickname<span class="token punctuation">)</span>
        <span class="token keyword">for</span> sock <span class="token keyword">in</span> SocketList<span class="token punctuation">:</span>
            sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'系统消息：'</span> <span class="token operator">+</span> nickname <span class="token operator">+</span> <span class="token string">'已下线！'</span><span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">#多线程：将收到的消息发送给所有客户端</span>
<span class="token keyword">def</span> <span class="token function">send_client</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span>nickname<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">try</span><span class="token punctuation">:</span>
        <span class="token comment"># s.send((','.join(Nickname)).encode('utf-8')) #将用户列表发送给各客户端</span>
        <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
            content <span class="token operator">=</span> read_client<span class="token punctuation">(</span>s<span class="token punctuation">,</span>nickname<span class="token punctuation">)</span> <span class="token comment">#客户端消息</span>
            <span class="token keyword">if</span> content <span class="token keyword">is</span> <span class="token boolean">None</span><span class="token punctuation">:</span> <span class="token comment">#如果没有结束循环</span>
                <span class="token keyword">break</span>
            <span class="token keyword">else</span><span class="token punctuation">:</span> <span class="token comment">#如果有将消息保存到历史记录</span>
                <span class="token comment"># TextList.append(str(addr)+': '+content)</span>
                TextList<span class="token punctuation">.</span>append<span class="token punctuation">(</span>nickname <span class="token operator">+</span> <span class="token string">': '</span> <span class="token operator">+</span> content<span class="token punctuation">)</span>
            <span class="token comment">#将一个客户端发送过来的数据广播给其他客户端</span>
            <span class="token keyword">for</span> sock <span class="token keyword">in</span> SocketList<span class="token punctuation">:</span>
                <span class="token comment"># sock.send((str(addr)+': '+content).encode('utf-8'))</span>
                sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span>nickname <span class="token operator">+</span> <span class="token string">': '</span> <span class="token operator">+</span> content<span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">except</span> Exception <span class="token keyword">as</span> e<span class="token punctuation">:</span>
        <span class="token comment"># print(repr())</span>
        <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'广播未成功！'</span><span class="token punctuation">)</span>

<span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
    client<span class="token punctuation">,</span>addr <span class="token operator">=</span> server<span class="token punctuation">.</span>accept<span class="token punctuation">(</span><span class="token punctuation">)</span>
    SocketList<span class="token punctuation">.</span>append<span class="token punctuation">(</span>client<span class="token punctuation">)</span>

    nickname <span class="token operator">=</span> client<span class="token punctuation">.</span>recv<span class="token punctuation">(</span><span class="token number">2048</span><span class="token punctuation">)</span><span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span>
    <span class="token comment"># print(str(addr)+'已加入！')</span>

    <span class="token keyword">if</span> nickname <span class="token keyword">in</span> Nickname<span class="token punctuation">:</span>
        i <span class="token operator">=</span> <span class="token number">1</span>
        <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
            <span class="token keyword">if</span> nickname<span class="token operator">+</span><span class="token builtin">str</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span> <span class="token keyword">in</span> Nickname<span class="token punctuation">:</span>
                i <span class="token operator">=</span> i<span class="token operator">+</span><span class="token number">1</span>
            <span class="token keyword">else</span><span class="token punctuation">:</span>
                nickname <span class="token operator">=</span> nickname <span class="token operator">+</span> <span class="token builtin">str</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span>
                <span class="token keyword">break</span>
    Nickname<span class="token punctuation">.</span>append<span class="token punctuation">(</span>nickname<span class="token punctuation">)</span>
    <span class="token keyword">print</span><span class="token punctuation">(</span>nickname <span class="token operator">+</span> <span class="token string">'已加入！'</span><span class="token punctuation">)</span>

    <span class="token keyword">for</span> sock <span class="token keyword">in</span> SocketList<span class="token punctuation">:</span>
        sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'系统消息：'</span> <span class="token operator">+</span> nickname <span class="token operator">+</span> <span class="token string">'已加入！'</span><span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

    <span class="token comment"># #历史消息生成</span>
    <span class="token comment"># if len(TextList)==0:</span>
    <span class="token comment">#     client.send('No message.'.encode('utf-8'))</span>
    <span class="token comment"># else:</span>
    <span class="token comment">#     client.send('\n'.join(TextList).encode('utf-8'))</span>

    cnt <span class="token operator">=</span> cnt <span class="token operator">+</span> <span class="token number">1</span>

    <span class="token comment">#每当有客户连接后，就启动一个线程为其服务</span>
    <span class="token comment">#加入线程中跑，加入函数为send_client，参数为client,nickname</span>
    threading<span class="token punctuation">.</span>Thread<span class="token punctuation">(</span>target<span class="token operator">=</span>send_client<span class="token punctuation">,</span> args<span class="token operator">=</span><span class="token punctuation">(</span>client<span class="token punctuation">,</span>nickname<span class="token punctuation">,</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>start<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment">#客户端</span>
<span class="token keyword">import</span> socket
<span class="token keyword">import</span> threading
<span class="token keyword">from</span> tkinter <span class="token keyword">import</span> <span class="token operator">*</span>
<span class="token keyword">import</span> tkinter<span class="token punctuation">.</span>messagebox <span class="token comment">#弹窗库</span>
<span class="token keyword">from</span> tkinter <span class="token keyword">import</span> scrolledtext  <span class="token comment">#滚动文本框</span>

server_host <span class="token operator">=</span> socket<span class="token punctuation">.</span>gethostname<span class="token punctuation">(</span><span class="token punctuation">)</span>
server_port <span class="token operator">=</span> <span class="token number">9999</span>

client <span class="token operator">=</span> socket<span class="token punctuation">.</span>socket<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#创建socket对象</span>
<span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'Connecting......'</span><span class="token punctuation">)</span>


<span class="token comment">#登入窗口：输入呢称</span>
<span class="token keyword">def</span> <span class="token function">LoginWindow</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    root <span class="token operator">=</span> Tk<span class="token punctuation">(</span><span class="token punctuation">)</span>
    root<span class="token punctuation">.</span>title<span class="token punctuation">(</span><span class="token string">'一起来聊天 · 登录'</span><span class="token punctuation">)</span> <span class="token comment">#窗口标题</span>
    root<span class="token punctuation">.</span>geometry<span class="token punctuation">(</span><span class="token string">'300x150'</span><span class="token punctuation">)</span> <span class="token comment">#窗口大小</span>
    root<span class="token punctuation">.</span>geometry<span class="token punctuation">(</span><span class="token string">'+500+300'</span><span class="token punctuation">)</span> <span class="token comment">#改变窗体位置（‘+横坐标+纵坐标’）</span>
    nickname <span class="token operator">=</span> StringVar<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#昵称变量（对象）:在使用界面编程的时候，有些时候是需要跟踪变量的值的变化，以保证值的变更随时可以显示在界面上</span>
    root<span class="token punctuation">.</span>resizable<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token comment">#将窗口大小设置为不可变</span>

    <span class="token comment">#登录函数（检查用户名是否为空，以及长度）</span>
    <span class="token keyword">def</span> <span class="token function">Login_in</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
        name <span class="token operator">=</span> nickname<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#????</span>
        <span class="token keyword">if</span> <span class="token keyword">not</span> name<span class="token punctuation">:</span>
            tkinter<span class="token punctuation">.</span>messagebox<span class="token punctuation">.</span>showwarning<span class="token punctuation">(</span><span class="token string">'Warning'</span><span class="token punctuation">,</span> message<span class="token operator">=</span><span class="token string">'用户名为空！'</span><span class="token punctuation">)</span> <span class="token comment">#消息警告框</span>
        <span class="token keyword">elif</span> <span class="token builtin">len</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span> <span class="token operator">></span> <span class="token number">10</span><span class="token punctuation">:</span>
            tkinter<span class="token punctuation">.</span>messagebox<span class="token punctuation">.</span>showwarning<span class="token punctuation">(</span><span class="token string">'Warning'</span><span class="token punctuation">,</span> message<span class="token operator">=</span><span class="token string">'用户名过长！最多为十个字符！'</span><span class="token punctuation">)</span>
        <span class="token keyword">else</span><span class="token punctuation">:</span>
            root<span class="token punctuation">.</span>destroy<span class="token punctuation">(</span><span class="token punctuation">)</span>
            client<span class="token punctuation">.</span>connect<span class="token punctuation">(</span><span class="token punctuation">(</span>server_host<span class="token punctuation">,</span> server_port<span class="token punctuation">)</span><span class="token punctuation">)</span>  <span class="token comment"># 连接服务端，指定主机和端口</span>
            <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'Connecting is successful!'</span><span class="token punctuation">)</span>
            client<span class="token punctuation">.</span>send<span class="token punctuation">(</span>name<span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>  <span class="token comment"># 传递用户昵称</span>
            ChatRoom<span class="token punctuation">(</span>name<span class="token punctuation">)</span>  <span class="token comment"># 打开聊天窗口</span>

    <span class="token comment">#登录按钮、输入提示标签、输入框</span>
    Button<span class="token punctuation">(</span>root<span class="token punctuation">,</span> text<span class="token operator">=</span><span class="token string">"登录"</span><span class="token punctuation">,</span> command<span class="token operator">=</span>Login_in<span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">8</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">90</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">35</span><span class="token punctuation">)</span>
    Label<span class="token punctuation">(</span>root<span class="token punctuation">,</span> text<span class="token operator">=</span><span class="token string">'请输入昵称'</span><span class="token punctuation">,</span> font<span class="token operator">=</span><span class="token punctuation">(</span><span class="token string">'Fangsong'</span><span class="token punctuation">,</span> <span class="token number">12</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">10</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">20</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">50</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">80</span><span class="token punctuation">)</span>
    Entry<span class="token punctuation">(</span>root<span class="token punctuation">,</span> textvariable<span class="token operator">=</span>nickname<span class="token punctuation">,</span> font<span class="token operator">=</span><span class="token punctuation">(</span><span class="token string">'Fangsong'</span><span class="token punctuation">,</span> <span class="token number">11</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">30</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">30</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">180</span><span class="token punctuation">)</span>

    root<span class="token punctuation">.</span>mainloop<span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">#聊天窗口</span>
<span class="token keyword">def</span> <span class="token function">ChatRoom</span><span class="token punctuation">(</span>nickname<span class="token punctuation">)</span><span class="token punctuation">:</span>
    root <span class="token operator">=</span> Tk<span class="token punctuation">(</span><span class="token punctuation">)</span>
    root<span class="token punctuation">.</span>geometry<span class="token punctuation">(</span><span class="token string">'650x400'</span><span class="token punctuation">)</span>  <span class="token comment"># 窗口大小</span>
    root<span class="token punctuation">.</span>resizable<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>  <span class="token comment"># 将窗口大小设置为不可变</span>
    root<span class="token punctuation">.</span>geometry<span class="token punctuation">(</span><span class="token string">'+500+300'</span><span class="token punctuation">)</span>  <span class="token comment"># 改变窗体位置（‘+横坐标+纵坐标’）</span>

    <span class="token comment"># content = client.recv(2048).decode('utf-8')</span>
    <span class="token comment"># if content != 'No message.':</span>
    <span class="token comment">#     past_text = content + '\n------以上是历史消息------\n'</span>

    <span class="token comment"># 从服务器端获取当前用户列表</span>
    <span class="token comment"># UserList = []</span>
    <span class="token comment"># UserList = client.recv(2048).decode('utf-8').split(',')</span>
    <span class="token comment"># UserList.insert(0, '------当前用户列表------')</span>

    <span class="token comment"># 窗口标题</span>
    <span class="token comment"># nickname = UserList[len(UserList)-1]</span>
    root<span class="token punctuation">.</span>title<span class="token punctuation">(</span><span class="token string">'一起来聊天 · '</span> <span class="token operator">+</span> nickname<span class="token punctuation">)</span>

    <span class="token comment"># name_text = StringVar()</span>
    <span class="token comment"># name_text.set(UserList)  # 用户列表文本设置</span>
    <span class="token comment"># listbox1 = Listbox(root, listvariable=name_text)  # 用户列表，使用Listbox组件</span>
    <span class="token comment"># listbox1.place(x=5, y=0, width=500, height=400)</span>

    <span class="token comment">#聊天界面</span>
    content <span class="token operator">=</span> client<span class="token punctuation">.</span>recv<span class="token punctuation">(</span><span class="token number">2048</span><span class="token punctuation">)</span><span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span>
    ChatBox <span class="token operator">=</span> scrolledtext<span class="token punctuation">.</span>ScrolledText<span class="token punctuation">(</span>root<span class="token punctuation">)</span>  <span class="token comment"># 聊天信息窗口，使用ScrolledText组件制作</span>
    ChatBox<span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">5</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">500</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">300</span><span class="token punctuation">)</span>
    <span class="token comment"># ChatBox.pack()</span>
    ChatBox<span class="token punctuation">.</span>insert<span class="token punctuation">(</span><span class="token string">'end'</span><span class="token punctuation">,</span>content<span class="token punctuation">)</span>

    <span class="token keyword">def</span> <span class="token function">read_server</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
            content <span class="token operator">=</span> c<span class="token punctuation">.</span>recv<span class="token punctuation">(</span><span class="token number">2048</span><span class="token punctuation">)</span><span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span>
            ChatBox<span class="token punctuation">.</span>insert<span class="token punctuation">(</span><span class="token string">'end'</span><span class="token punctuation">,</span> <span class="token string">'\n'</span><span class="token operator">+</span>content<span class="token operator">+</span><span class="token string">'\n\n'</span><span class="token punctuation">)</span>
            ChatBox<span class="token punctuation">.</span>see<span class="token punctuation">(</span>tkinter<span class="token punctuation">.</span>END<span class="token punctuation">)</span>  <span class="token comment"># ScrolledText组件方法，自动定位到结尾，否则只有消息在涨，窗口拖动条不动</span>
            ChatBox<span class="token punctuation">.</span>update<span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token comment"># 更新聊天信息窗口，显示新的信息</span>
    threading<span class="token punctuation">.</span>Thread<span class="token punctuation">(</span>target<span class="token operator">=</span>read_server<span class="token punctuation">,</span> args<span class="token operator">=</span><span class="token punctuation">(</span>client<span class="token punctuation">,</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>start<span class="token punctuation">(</span><span class="token punctuation">)</span>

    <span class="token comment">#聊天输入框</span>
    word <span class="token operator">=</span> StringVar<span class="token punctuation">(</span><span class="token punctuation">)</span>
    word<span class="token punctuation">.</span><span class="token builtin">set</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span>
    SentBox <span class="token operator">=</span> Entry<span class="token punctuation">(</span>root<span class="token punctuation">,</span>width<span class="token operator">=</span><span class="token number">140</span><span class="token punctuation">,</span>textvariable<span class="token operator">=</span>word<span class="token punctuation">)</span> <span class="token comment">#建一个输入框</span>
    SentBox<span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">5</span><span class="token punctuation">,</span>y<span class="token operator">=</span><span class="token number">305</span><span class="token punctuation">,</span>width<span class="token operator">=</span><span class="token number">600</span><span class="token punctuation">,</span>height<span class="token operator">=</span><span class="token number">95</span><span class="token punctuation">)</span> <span class="token comment">#设置大小和位置</span>

    <span class="token comment">#发送按钮</span>
    <span class="token keyword">def</span> <span class="token function">sendtext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
        content <span class="token operator">=</span> word<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#获得文本内容</span>
        <span class="token keyword">if</span> content<span class="token operator">==</span><span class="token string">'end'</span><span class="token punctuation">:</span>
            client<span class="token punctuation">.</span>close<span class="token punctuation">(</span><span class="token punctuation">)</span>
        client<span class="token punctuation">.</span>send<span class="token punctuation">(</span>content<span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        word<span class="token punctuation">.</span><span class="token builtin">set</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span> <span class="token comment">#用了一个标记记录点击的状态，不管内容是什么点了就变</span>

    sendButton <span class="token operator">=</span> Button<span class="token punctuation">(</span>root<span class="token punctuation">,</span> text<span class="token operator">=</span><span class="token string">'发 送'</span><span class="token punctuation">,</span> font<span class="token operator">=</span><span class="token punctuation">(</span><span class="token string">'Fangsong'</span><span class="token punctuation">,</span> <span class="token number">18</span><span class="token punctuation">)</span><span class="token punctuation">,</span> bg<span class="token operator">=</span><span class="token string">'white'</span><span class="token punctuation">,</span> command<span class="token operator">=</span>sendtext<span class="token punctuation">)</span>
    sendButton<span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">500</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">305</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">150</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">95</span><span class="token punctuation">)</span>

    root<span class="token punctuation">.</span>mainloop<span class="token punctuation">(</span><span class="token punctuation">)</span>

LoginWindow<span class="token punctuation">(</span><span class="token punctuation">)</span>

<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h3 id="0-67"><a href="#0-67" class="headerlink" title="0.67"></a><strong>0.67</strong></h3><p><strong>作用：0.65上改了点细节（可视化界面加了个图片），先能用……要解决子线程关闭问题</strong></p>
<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment">#服务器</span>
<span class="token comment">#服务端</span>
<span class="token keyword">import</span> socket
<span class="token keyword">import</span> threading


host <span class="token operator">=</span> socket<span class="token punctuation">.</span>gethostname<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#获取当前主机的IP地址</span>
port <span class="token operator">=</span> <span class="token number">9999</span> <span class="token comment">#设置防火墙开放端口</span>
SocketList <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token comment">#存储客户端套接字的列表</span>
TextList <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token comment">#存储聊天记录</span>
Nickname <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token comment">#存储用户呢称</span>
cnt <span class="token operator">=</span> <span class="token number">0</span> <span class="token comment">#当前客户端人数</span>
<span class="token keyword">print</span><span class="token punctuation">(</span>host<span class="token punctuation">)</span>

server <span class="token operator">=</span> socket<span class="token punctuation">.</span>socket<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#创建server对象</span>
server<span class="token punctuation">.</span>bind<span class="token punctuation">(</span><span class="token punctuation">(</span>host<span class="token punctuation">,</span>port<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">#绑定</span>
server<span class="token punctuation">.</span>listen<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#监听</span>
<span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'服务器准备就绪！'</span><span class="token punctuation">)</span>

<span class="token comment">#接收一个客户端连接，及其发送来数据</span>
<span class="token keyword">def</span> <span class="token function">read_client</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span>nickname<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">try</span><span class="token punctuation">:</span>
        <span class="token comment">#接受客户端发送来的数据</span>
        <span class="token keyword">return</span> s<span class="token punctuation">.</span>recv<span class="token punctuation">(</span><span class="token number">2048</span><span class="token punctuation">)</span><span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span>
    <span class="token keyword">except</span><span class="token punctuation">:</span>
        <span class="token comment">#客户端异常，连接失败，则删除该socket</span>
        <span class="token comment"># print(str(addr)+'已下线！')</span>
        <span class="token keyword">print</span><span class="token punctuation">(</span>nickname <span class="token operator">+</span> <span class="token string">'已下线！'</span><span class="token punctuation">)</span>
        SocketList<span class="token punctuation">.</span>remove<span class="token punctuation">(</span>s<span class="token punctuation">)</span>
        Nickname<span class="token punctuation">.</span>remove<span class="token punctuation">(</span>nickname<span class="token punctuation">)</span>
        <span class="token keyword">for</span> sock <span class="token keyword">in</span> SocketList<span class="token punctuation">:</span>
            sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'系统消息：'</span> <span class="token operator">+</span> nickname <span class="token operator">+</span> <span class="token string">'已下线！'</span><span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">#多线程：将收到的消息发送给所有客户端</span>
<span class="token keyword">def</span> <span class="token function">send_client</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span>nickname<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">try</span><span class="token punctuation">:</span>
        <span class="token comment"># s.send((','.join(Nickname)).encode('utf-8')) #将用户列表发送给各客户端</span>
        <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
            content <span class="token operator">=</span> read_client<span class="token punctuation">(</span>s<span class="token punctuation">,</span>nickname<span class="token punctuation">)</span> <span class="token comment">#客户端消息</span>
            <span class="token keyword">if</span> content <span class="token keyword">is</span> <span class="token boolean">None</span><span class="token punctuation">:</span> <span class="token comment">#如果没有结束循环</span>
                <span class="token keyword">break</span>
            <span class="token keyword">else</span><span class="token punctuation">:</span> <span class="token comment">#如果有将消息保存到历史记录</span>
                <span class="token comment"># TextList.append(str(addr)+': '+content)</span>
                TextList<span class="token punctuation">.</span>append<span class="token punctuation">(</span>nickname <span class="token operator">+</span> <span class="token string">': '</span> <span class="token operator">+</span> content<span class="token punctuation">)</span>
            <span class="token comment">#将一个客户端发送过来的数据广播给其他客户端</span>
            <span class="token keyword">for</span> sock <span class="token keyword">in</span> SocketList<span class="token punctuation">:</span>
                <span class="token comment"># sock.send((str(addr)+': '+content).encode('utf-8'))</span>
                sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span>nickname <span class="token operator">+</span> <span class="token string">': '</span> <span class="token operator">+</span> content<span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">except</span> Exception <span class="token keyword">as</span> e<span class="token punctuation">:</span>
        <span class="token comment"># print(repr())</span>
        <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'广播未成功！'</span><span class="token punctuation">)</span>

<span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
    client<span class="token punctuation">,</span>addr <span class="token operator">=</span> server<span class="token punctuation">.</span>accept<span class="token punctuation">(</span><span class="token punctuation">)</span>
    SocketList<span class="token punctuation">.</span>append<span class="token punctuation">(</span>client<span class="token punctuation">)</span>

    nickname <span class="token operator">=</span> client<span class="token punctuation">.</span>recv<span class="token punctuation">(</span><span class="token number">2048</span><span class="token punctuation">)</span><span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span>
    <span class="token comment"># print(str(addr)+'已加入！')</span>

    <span class="token keyword">if</span> nickname <span class="token keyword">in</span> Nickname<span class="token punctuation">:</span>
        i <span class="token operator">=</span> <span class="token number">1</span>
        <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
            <span class="token keyword">if</span> nickname<span class="token operator">+</span><span class="token builtin">str</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span> <span class="token keyword">in</span> Nickname<span class="token punctuation">:</span>
                i <span class="token operator">=</span> i<span class="token operator">+</span><span class="token number">1</span>
            <span class="token keyword">else</span><span class="token punctuation">:</span>
                nickname <span class="token operator">=</span> nickname <span class="token operator">+</span> <span class="token builtin">str</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span>
                <span class="token keyword">break</span>
    Nickname<span class="token punctuation">.</span>append<span class="token punctuation">(</span>nickname<span class="token punctuation">)</span>
    <span class="token keyword">print</span><span class="token punctuation">(</span>nickname <span class="token operator">+</span> <span class="token string">'已加入！'</span><span class="token punctuation">)</span>

    <span class="token keyword">for</span> sock <span class="token keyword">in</span> SocketList<span class="token punctuation">:</span>
        sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'系统消息：'</span> <span class="token operator">+</span> nickname <span class="token operator">+</span> <span class="token string">'已加入！'</span><span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

    <span class="token comment"># #历史消息生成</span>
    <span class="token comment"># if len(TextList)==0:</span>
    <span class="token comment">#     client.send('No message.'.encode('utf-8'))</span>
    <span class="token comment"># else:</span>
    <span class="token comment">#     client.send('\n'.join(TextList).encode('utf-8'))</span>

    cnt <span class="token operator">=</span> cnt <span class="token operator">+</span> <span class="token number">1</span>

    <span class="token comment">#每当有客户连接后，就启动一个线程为其服务</span>
    <span class="token comment">#加入线程中跑，加入函数为send_client，参数为client,nickname</span>
    threading<span class="token punctuation">.</span>Thread<span class="token punctuation">(</span>target<span class="token operator">=</span>send_client<span class="token punctuation">,</span> args<span class="token operator">=</span><span class="token punctuation">(</span>client<span class="token punctuation">,</span>nickname<span class="token punctuation">,</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>start<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment">#客户端</span>
<span class="token keyword">import</span> socket
<span class="token keyword">import</span> threading
<span class="token keyword">from</span> tkinter <span class="token keyword">import</span> <span class="token operator">*</span>
<span class="token keyword">import</span> tkinter<span class="token punctuation">.</span>messagebox <span class="token comment">#弹窗库</span>
<span class="token keyword">from</span> tkinter <span class="token keyword">import</span> scrolledtext  <span class="token comment">#滚动文本框</span>

server_host <span class="token operator">=</span> socket<span class="token punctuation">.</span>gethostname<span class="token punctuation">(</span><span class="token punctuation">)</span>
server_port <span class="token operator">=</span> <span class="token number">9999</span>

client <span class="token operator">=</span> socket<span class="token punctuation">.</span>socket<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#创建socket对象</span>
<span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'Connecting......'</span><span class="token punctuation">)</span>


<span class="token comment">#登入窗口：输入呢称</span>
<span class="token keyword">def</span> <span class="token function">LoginWindow</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    root <span class="token operator">=</span> Tk<span class="token punctuation">(</span><span class="token punctuation">)</span>
    root<span class="token punctuation">.</span>title<span class="token punctuation">(</span><span class="token string">'一起来聊天 · 登录'</span><span class="token punctuation">)</span> <span class="token comment">#窗口标题</span>
    root<span class="token punctuation">.</span>geometry<span class="token punctuation">(</span><span class="token string">'300x150'</span><span class="token punctuation">)</span> <span class="token comment">#窗口大小</span>
    root<span class="token punctuation">.</span>geometry<span class="token punctuation">(</span><span class="token string">'+500+300'</span><span class="token punctuation">)</span> <span class="token comment">#改变窗体位置（‘+横坐标+纵坐标’）</span>
    nickname <span class="token operator">=</span> StringVar<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#昵称变量（对象）:在使用界面编程的时候，有些时候是需要跟踪变量的值的变化，以保证值的变更随时可以显示在界面上</span>
    root<span class="token punctuation">.</span>resizable<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token comment">#将窗口大小设置为不可变</span>

    <span class="token comment">#登录函数（检查用户名是否为空，以及长度）</span>
    <span class="token keyword">def</span> <span class="token function">Login_in</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
        name <span class="token operator">=</span> nickname<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#????</span>
        <span class="token keyword">if</span> <span class="token keyword">not</span> name<span class="token punctuation">:</span>
            tkinter<span class="token punctuation">.</span>messagebox<span class="token punctuation">.</span>showwarning<span class="token punctuation">(</span><span class="token string">'Warning'</span><span class="token punctuation">,</span> message<span class="token operator">=</span><span class="token string">'用户名为空！'</span><span class="token punctuation">)</span> <span class="token comment">#消息警告框</span>
        <span class="token keyword">elif</span> <span class="token builtin">len</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span> <span class="token operator">></span> <span class="token number">10</span><span class="token punctuation">:</span>
            tkinter<span class="token punctuation">.</span>messagebox<span class="token punctuation">.</span>showwarning<span class="token punctuation">(</span><span class="token string">'Warning'</span><span class="token punctuation">,</span> message<span class="token operator">=</span><span class="token string">'用户名过长！最多为十个字符！'</span><span class="token punctuation">)</span>
        <span class="token keyword">else</span><span class="token punctuation">:</span>
            root<span class="token punctuation">.</span>destroy<span class="token punctuation">(</span><span class="token punctuation">)</span>
            client<span class="token punctuation">.</span>connect<span class="token punctuation">(</span><span class="token punctuation">(</span>server_host<span class="token punctuation">,</span> server_port<span class="token punctuation">)</span><span class="token punctuation">)</span>  <span class="token comment"># 连接服务端，指定主机和端口</span>
            <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'Connecting is successful!'</span><span class="token punctuation">)</span>
            client<span class="token punctuation">.</span>send<span class="token punctuation">(</span>name<span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>  <span class="token comment"># 传递用户昵称</span>
            ChatRoom<span class="token punctuation">(</span>name<span class="token punctuation">)</span>  <span class="token comment"># 打开聊天窗口</span>

    <span class="token comment">#登录按钮、输入提示标签、输入框</span>
    Button<span class="token punctuation">(</span>root<span class="token punctuation">,</span> text<span class="token operator">=</span><span class="token string">"登录"</span><span class="token punctuation">,</span> command<span class="token operator">=</span>Login_in<span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">8</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">90</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">35</span><span class="token punctuation">)</span>
    Label<span class="token punctuation">(</span>root<span class="token punctuation">,</span> text<span class="token operator">=</span><span class="token string">'请输入昵称'</span><span class="token punctuation">,</span> font<span class="token operator">=</span><span class="token punctuation">(</span><span class="token string">'Fangsong'</span><span class="token punctuation">,</span> <span class="token number">12</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">10</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">20</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">50</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">80</span><span class="token punctuation">)</span>
    Entry<span class="token punctuation">(</span>root<span class="token punctuation">,</span> textvariable<span class="token operator">=</span>nickname<span class="token punctuation">,</span> font<span class="token operator">=</span><span class="token punctuation">(</span><span class="token string">'Fangsong'</span><span class="token punctuation">,</span> <span class="token number">11</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">30</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">30</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">180</span><span class="token punctuation">)</span>

    root<span class="token punctuation">.</span>mainloop<span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">#聊天窗口</span>
<span class="token keyword">def</span> <span class="token function">ChatRoom</span><span class="token punctuation">(</span>nickname<span class="token punctuation">)</span><span class="token punctuation">:</span>
    root <span class="token operator">=</span> Tk<span class="token punctuation">(</span><span class="token punctuation">)</span>
    root<span class="token punctuation">.</span>geometry<span class="token punctuation">(</span><span class="token string">'650x400'</span><span class="token punctuation">)</span>  <span class="token comment"># 窗口大小</span>
    root<span class="token punctuation">.</span>resizable<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>  <span class="token comment"># 将窗口大小设置为不可变</span>
    root<span class="token punctuation">.</span>geometry<span class="token punctuation">(</span><span class="token string">'+500+300'</span><span class="token punctuation">)</span>  <span class="token comment"># 改变窗体位置（‘+横坐标+纵坐标’）</span>

    <span class="token comment"># content = client.recv(2048).decode('utf-8')</span>
    <span class="token comment"># if content != 'No message.':</span>
    <span class="token comment">#     past_text = content + '\n------以上是历史消息------\n'</span>

    <span class="token comment"># 从服务器端获取当前用户列表</span>
    <span class="token comment"># UserList = []</span>
    <span class="token comment"># UserList = client.recv(2048).decode('utf-8').split(',')</span>
    <span class="token comment"># UserList.insert(0, '------当前用户列表------')</span>

    <span class="token comment"># 窗口标题</span>
    <span class="token comment"># nickname = UserList[len(UserList)-1]</span>
    root<span class="token punctuation">.</span>title<span class="token punctuation">(</span><span class="token string">'一起来聊天 · '</span> <span class="token operator">+</span> nickname<span class="token punctuation">)</span>

    <span class="token comment"># name_text = StringVar()</span>
    <span class="token comment"># name_text.set(UserList)  # 用户列表文本设置</span>
    <span class="token comment"># listbox1 = Listbox(root, listvariable=name_text)  # 用户列表，使用Listbox组件</span>
    <span class="token comment"># listbox1.place(x=5, y=0, width=500, height=400)</span>

    img_png <span class="token operator">=</span> PhotoImage<span class="token punctuation">(</span><span class="token builtin">file</span><span class="token operator">=</span><span class="token string">'QQ图片20220901201640.png'</span><span class="token punctuation">)</span>
    label_img <span class="token operator">=</span> Label<span class="token punctuation">(</span>root<span class="token punctuation">,</span> image<span class="token operator">=</span>img_png<span class="token punctuation">)</span>
    label_img<span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">400</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">350</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">300</span><span class="token punctuation">)</span>

    <span class="token comment">#聊天界面</span>
    content <span class="token operator">=</span> client<span class="token punctuation">.</span>recv<span class="token punctuation">(</span><span class="token number">2048</span><span class="token punctuation">)</span><span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span>
    ChatBox <span class="token operator">=</span> scrolledtext<span class="token punctuation">.</span>ScrolledText<span class="token punctuation">(</span>root<span class="token punctuation">)</span>  <span class="token comment"># 聊天信息窗口，使用ScrolledText组件制作</span>
    ChatBox<span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">5</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">470</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">300</span><span class="token punctuation">)</span>
    <span class="token comment"># ChatBox.pack()</span>
    ChatBox<span class="token punctuation">.</span>insert<span class="token punctuation">(</span><span class="token string">'end'</span><span class="token punctuation">,</span>content<span class="token punctuation">)</span>

    <span class="token keyword">def</span> <span class="token function">read_server</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
            content <span class="token operator">=</span> c<span class="token punctuation">.</span>recv<span class="token punctuation">(</span><span class="token number">2048</span><span class="token punctuation">)</span><span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span>
            ChatBox<span class="token punctuation">.</span>insert<span class="token punctuation">(</span><span class="token string">'end'</span><span class="token punctuation">,</span> <span class="token string">'\n'</span><span class="token operator">+</span>content<span class="token operator">+</span><span class="token string">'\n\n'</span><span class="token punctuation">)</span>
            ChatBox<span class="token punctuation">.</span>see<span class="token punctuation">(</span>tkinter<span class="token punctuation">.</span>END<span class="token punctuation">)</span>  <span class="token comment"># ScrolledText组件方法，自动定位到结尾，否则只有消息在涨，窗口拖动条不动</span>
            ChatBox<span class="token punctuation">.</span>update<span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token comment"># 更新聊天信息窗口，显示新的信息</span>
    threading<span class="token punctuation">.</span>Thread<span class="token punctuation">(</span>target<span class="token operator">=</span>read_server<span class="token punctuation">,</span> args<span class="token operator">=</span><span class="token punctuation">(</span>client<span class="token punctuation">,</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>start<span class="token punctuation">(</span><span class="token punctuation">)</span>

    <span class="token comment">#聊天输入框</span>
    word <span class="token operator">=</span> StringVar<span class="token punctuation">(</span><span class="token punctuation">)</span>
    word<span class="token punctuation">.</span><span class="token builtin">set</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span>
    SentBox <span class="token operator">=</span> Entry<span class="token punctuation">(</span>root<span class="token punctuation">,</span>width<span class="token operator">=</span><span class="token number">140</span><span class="token punctuation">,</span>textvariable<span class="token operator">=</span>word<span class="token punctuation">)</span> <span class="token comment">#建一个输入框</span>
    SentBox<span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">5</span><span class="token punctuation">,</span>y<span class="token operator">=</span><span class="token number">305</span><span class="token punctuation">,</span>width<span class="token operator">=</span><span class="token number">475</span><span class="token punctuation">,</span>height<span class="token operator">=</span><span class="token number">90</span><span class="token punctuation">)</span> <span class="token comment">#设置大小和位置</span>

    <span class="token comment">#发送按钮</span>
    <span class="token keyword">def</span> <span class="token function">sendtext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
        content <span class="token operator">=</span> word<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#获得文本内容</span>
        <span class="token keyword">if</span> content<span class="token operator">==</span><span class="token string">'end'</span><span class="token punctuation">:</span>
            client<span class="token punctuation">.</span>close<span class="token punctuation">(</span><span class="token punctuation">)</span>
        client<span class="token punctuation">.</span>send<span class="token punctuation">(</span>content<span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        word<span class="token punctuation">.</span><span class="token builtin">set</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span> <span class="token comment">#用了一个标记记录点击的状态，不管内容是什么点了就变</span>

    sendButton <span class="token operator">=</span> Button<span class="token punctuation">(</span>root<span class="token punctuation">,</span> text<span class="token operator">=</span><span class="token string">'发 送'</span><span class="token punctuation">,</span> font<span class="token operator">=</span><span class="token punctuation">(</span><span class="token string">'Fangsong'</span><span class="token punctuation">,</span> <span class="token number">18</span><span class="token punctuation">)</span><span class="token punctuation">,</span> bg<span class="token operator">=</span><span class="token string">'white'</span><span class="token punctuation">,</span> command<span class="token operator">=</span>sendtext<span class="token punctuation">)</span>
    sendButton<span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">490</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">308</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">150</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">85</span><span class="token punctuation">)</span>

    root<span class="token punctuation">.</span>mainloop<span class="token punctuation">(</span><span class="token punctuation">)</span>

LoginWindow<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>



<blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/zc666ying/article/details/104444733">(29条消息) Python—多线程编程（一）线程的创建，管理，停止_onesalatree的博客-CSDN博客_python线程开始结束</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/wangyunhe5120/article/details/121846368">(29条消息) python GUI 多线程 暂停 恢复 结束_为此残生的博客-CSDN博客</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_41082014/article/details/92085252">(29条消息) Python多线程的退出控制_Messy..的博客-CSDN博客_python关闭线程的方法</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_45956730/article/details/124120897">(29条消息) python多线程之 终止子线程_水w的博客-CSDN博客_python 结束线程</a></p>
</blockquote>
<h1 id="实训一阶段2：可靠传输"><a href="#实训一阶段2：可靠传输" class="headerlink" title="实训一阶段2：可靠传输"></a>实训一阶段2：可靠传输</h1><blockquote>
<p>要求：</p>
<p>了解聊天程序的一般原理；</p>
<p>按照带流量控制的协议改造聊天程序；</p>
<p>编程语言不限；</p>
<p>要能在两台PC上运行。</p>
</blockquote>
<h2 id="初级阶段5：可靠传输与流量控制"><a href="#初级阶段5：可靠传输与流量控制" class="headerlink" title="初级阶段5：可靠传输与流量控制"></a>初级阶段5：可靠传输与流量控制</h2><blockquote>
<p>可靠传输：使用<a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/405221648">差错检测技术</a>，接收方的数据链路层就可以检测出帧在传输过程中是否产生了误码。</p>
<p>如果可靠传输，能够在检测出误码之后，返回一个通知帧，告诉发送方之前传输的帧存在误码，也许可以解决误码重传的问题</p>
<ul>
<li>数据链路层传输差错：比特差错、分组丢失、分组失序、分组重复</li>
<li><strong>可靠传输</strong>：想方法实现<strong>发送端发送什么，接收端就收到什么</strong></li>
</ul>
</blockquote>
<p><img src="https://img-blog.csdnimg.cn/20210424181454154.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1Nzc4Njc2,size_16,color_FFFFFF,t_70" alt="img"></p>
<p><strong>计算机网络之流量控制（停止-等待协议1:1、滑动窗口：后退N帧协议GBN、选择重传协议SR）、滑动窗口、可靠传输机制</strong></p>
<p>1.什么是<a target="_blank" rel="noopener" href="https://so.csdn.net/so/search?q=%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6&spm=1001.2101.3001.7020">流量控制</a>？</p>
<ul>
<li>流量控制是数据链路层的一种功能，流量控制对数据链路上的帧的发送速率进行控制，以使接收方有足够的缓冲空间来接受每个帧</li>
<li>流量控制的基本方法是由接收方控制发送方发送数据的速率</li>
<li>常见的流量控制方式有两种：<code>停止-等待协议、滑动窗口协议</code></li>
</ul>
<p>2.什么是可靠传输机制？</p>
<ul>
<li><p>​        可靠传输机制是为了使数据可以正确稳定的传输和接收而制定的规则。</p>
</li>
<li><p>数据链路层的可靠传输通常使用确认和超时重传两种机制来完成。</p>
</li>
<li><p>确认是一种无数据的控制帧，这种控制帧使得接收方可以让发送方知道哪些内容被正确接收。有些情况下为了提高传输效率，将确认捎带在一个回复帧中，称为捎带确认。</p>
</li>
<li><p>超时重传是指发送方在发送某一个数据帧以后就开始一个计时器，在一定时间内如果没有得到发送的数据帧的确认帧，那么就重新发送该数据帧，直到发送成功为止。</p>
</li>
<li><p>自动重传请求（Auto Repeat reQuest，ARQ），通过接收方请求发送方重传出错的数据帧来恢复出错的帧，是通信中用于处理信道所带来差错的方法之一。</p>
</li>
<li><p>传统自动重传请求分为三种，即停等式（Stop-and-Wait）ARQ、后退N帧（Go-Back-N）ARQ以及选择性重传（Selective Repeat）ARQ。后两种协议是滑动窗口技术与请求重发技术的结合，由于窗口尺寸开到足够大，帧在线路上可以连续地流动，因此又称为连续ARQ协议。</p>
</li>
</ul>
<p>3.什么是滑动窗口机制？</p>
<ul>
<li>滑动窗口协议的基本原理就是在任意时刻，发送方都维持了一个连续的允许发送的帧的序号，称为发送窗口；同时，接收方也维持了一个连续的允许接收的帧的序号，称为接收窗口。</li>
<li>发送窗口和接收窗口的序号的上下界不一定要一样，甚至大小也可以不同。<br>不同的滑动窗口协议窗口大小一般不同。</li>
<li>发送方窗口内的序列号代表了那些已经被发送，但是还没有被确认的帧，或者是那些可以被发送的帧。</li>
</ul>
<p>PS：直接看王道考研-计算机网络 3.4</p>
<h3 id="0-6-1"><a href="#0-6-1" class="headerlink" title="0.6"></a><strong>0.6</strong></h3><p><strong>作用：CRC校验有问题，基础功能实现</strong></p>
<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment">#客户端</span>
<span class="token keyword">import</span> socket
<span class="token keyword">import</span> threading
<span class="token keyword">from</span> tkinter <span class="token keyword">import</span> <span class="token operator">*</span>
<span class="token keyword">import</span> tkinter<span class="token punctuation">.</span>messagebox <span class="token comment">#弹窗库</span>
<span class="token keyword">from</span> tkinter <span class="token keyword">import</span> scrolledtext  <span class="token comment">#滚动文本框</span>

server_host <span class="token operator">=</span> socket<span class="token punctuation">.</span>gethostname<span class="token punctuation">(</span><span class="token punctuation">)</span>
server_port <span class="token operator">=</span> <span class="token number">9999</span>

client <span class="token operator">=</span> socket<span class="token punctuation">.</span>socket<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#创建socket对象</span>
<span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'Connecting......'</span><span class="token punctuation">)</span>


<span class="token comment">#登入窗口：输入呢称</span>
<span class="token keyword">def</span> <span class="token function">LoginWindow</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    root <span class="token operator">=</span> Tk<span class="token punctuation">(</span><span class="token punctuation">)</span>
    root<span class="token punctuation">.</span>title<span class="token punctuation">(</span><span class="token string">'一起来聊天 · 登录'</span><span class="token punctuation">)</span> <span class="token comment">#窗口标题</span>
    root<span class="token punctuation">.</span>geometry<span class="token punctuation">(</span><span class="token string">'300x150'</span><span class="token punctuation">)</span> <span class="token comment">#窗口大小</span>
    root<span class="token punctuation">.</span>geometry<span class="token punctuation">(</span><span class="token string">'+500+300'</span><span class="token punctuation">)</span> <span class="token comment">#改变窗体位置（‘+横坐标+纵坐标’）</span>
    nickname <span class="token operator">=</span> StringVar<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#昵称变量（对象）:在使用界面编程的时候，有些时候是需要跟踪变量的值的变化，以保证值的变更随时可以显示在界面上</span>
    root<span class="token punctuation">.</span>resizable<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token comment">#将窗口大小设置为不可变</span>

    <span class="token comment">#登录函数（检查用户名是否为空，以及长度）</span>
    <span class="token keyword">def</span> <span class="token function">Login_in</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
        name <span class="token operator">=</span> nickname<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#????</span>
        <span class="token keyword">if</span> <span class="token keyword">not</span> name<span class="token punctuation">:</span>
            tkinter<span class="token punctuation">.</span>messagebox<span class="token punctuation">.</span>showwarning<span class="token punctuation">(</span><span class="token string">'Warning'</span><span class="token punctuation">,</span> message<span class="token operator">=</span><span class="token string">'用户名为空！'</span><span class="token punctuation">)</span> <span class="token comment">#消息警告框</span>
        <span class="token keyword">elif</span> <span class="token builtin">len</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span> <span class="token operator">></span> <span class="token number">10</span><span class="token punctuation">:</span>
            tkinter<span class="token punctuation">.</span>messagebox<span class="token punctuation">.</span>showwarning<span class="token punctuation">(</span><span class="token string">'Warning'</span><span class="token punctuation">,</span> message<span class="token operator">=</span><span class="token string">'用户名过长！最多为十个字符！'</span><span class="token punctuation">)</span>
        <span class="token keyword">else</span><span class="token punctuation">:</span>
            root<span class="token punctuation">.</span>destroy<span class="token punctuation">(</span><span class="token punctuation">)</span>
            client<span class="token punctuation">.</span>connect<span class="token punctuation">(</span><span class="token punctuation">(</span>server_host<span class="token punctuation">,</span> server_port<span class="token punctuation">)</span><span class="token punctuation">)</span>  <span class="token comment"># 连接服务端，指定主机和端口</span>
            <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'Connecting is successful!'</span><span class="token punctuation">)</span>
            client<span class="token punctuation">.</span>send<span class="token punctuation">(</span>name<span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>  <span class="token comment"># 传递用户昵称</span>
            ChatRoom<span class="token punctuation">(</span>name<span class="token punctuation">)</span>  <span class="token comment"># 打开聊天窗口</span>

    <span class="token comment">#登录按钮、输入提示标签、输入框</span>
    Button<span class="token punctuation">(</span>root<span class="token punctuation">,</span> text<span class="token operator">=</span><span class="token string">"登录"</span><span class="token punctuation">,</span> command<span class="token operator">=</span>Login_in<span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">8</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">90</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">35</span><span class="token punctuation">)</span>
    Label<span class="token punctuation">(</span>root<span class="token punctuation">,</span> text<span class="token operator">=</span><span class="token string">'请输入昵称'</span><span class="token punctuation">,</span> font<span class="token operator">=</span><span class="token punctuation">(</span><span class="token string">'Fangsong'</span><span class="token punctuation">,</span> <span class="token number">12</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">10</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">20</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">50</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">80</span><span class="token punctuation">)</span>
    Entry<span class="token punctuation">(</span>root<span class="token punctuation">,</span> textvariable<span class="token operator">=</span>nickname<span class="token punctuation">,</span> font<span class="token operator">=</span><span class="token punctuation">(</span><span class="token string">'Fangsong'</span><span class="token punctuation">,</span> <span class="token number">11</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">30</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">30</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">180</span><span class="token punctuation">)</span>

    root<span class="token punctuation">.</span>mainloop<span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">#聊天窗口</span>
<span class="token keyword">def</span> <span class="token function">ChatRoom</span><span class="token punctuation">(</span>nickname<span class="token punctuation">)</span><span class="token punctuation">:</span>
    root <span class="token operator">=</span> Tk<span class="token punctuation">(</span><span class="token punctuation">)</span>
    root<span class="token punctuation">.</span>geometry<span class="token punctuation">(</span><span class="token string">'650x400'</span><span class="token punctuation">)</span>  <span class="token comment"># 窗口大小</span>
    root<span class="token punctuation">.</span>resizable<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>  <span class="token comment"># 将窗口大小设置为不可变</span>
    root<span class="token punctuation">.</span>geometry<span class="token punctuation">(</span><span class="token string">'+500+300'</span><span class="token punctuation">)</span>  <span class="token comment"># 改变窗体位置（‘+横坐标+纵坐标’）</span>

    <span class="token comment"># content = client.recv(2048).decode('utf-8')</span>
    <span class="token comment"># if content != 'No message.':</span>
    <span class="token comment">#     past_text = content + '\n------以上是历史消息------\n'</span>

    <span class="token comment"># 从服务器端获取当前用户列表</span>
    <span class="token comment"># UserList = []</span>
    <span class="token comment"># UserList = client.recv(2048).decode('utf-8').split(',')</span>
    <span class="token comment"># UserList.insert(0, '------当前用户列表------')</span>

    <span class="token comment"># 窗口标题</span>
    <span class="token comment"># nickname = UserList[len(UserList)-1]</span>
    root<span class="token punctuation">.</span>title<span class="token punctuation">(</span><span class="token string">'一起来聊天 · '</span> <span class="token operator">+</span> nickname<span class="token punctuation">)</span>

    <span class="token comment"># name_text = StringVar()</span>
    <span class="token comment"># name_text.set(UserList)  # 用户列表文本设置</span>
    <span class="token comment"># listbox1 = Listbox(root, listvariable=name_text)  # 用户列表，使用Listbox组件</span>
    <span class="token comment"># listbox1.place(x=5, y=0, width=500, height=400)</span>

    img_png <span class="token operator">=</span> PhotoImage<span class="token punctuation">(</span><span class="token builtin">file</span><span class="token operator">=</span><span class="token string">'QQ图片20220901201640.png'</span><span class="token punctuation">)</span>
    label_img <span class="token operator">=</span> Label<span class="token punctuation">(</span>root<span class="token punctuation">,</span> image<span class="token operator">=</span>img_png<span class="token punctuation">)</span>
    label_img<span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">400</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">350</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">300</span><span class="token punctuation">)</span>

    <span class="token comment">#聊天界面</span>
    <span class="token comment"># content = client.recv(2048).decode('utf-8')</span>
    ChatBox <span class="token operator">=</span> scrolledtext<span class="token punctuation">.</span>ScrolledText<span class="token punctuation">(</span>root<span class="token punctuation">)</span>  <span class="token comment"># 聊天信息窗口，使用ScrolledText组件制作</span>
    ChatBox<span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">5</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">470</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">300</span><span class="token punctuation">)</span>
    <span class="token comment"># ChatBox.pack()</span>
    <span class="token comment"># ChatBox.insert('end',content)</span>

    <span class="token keyword">def</span> <span class="token function">read_server</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
            content <span class="token operator">=</span> c<span class="token punctuation">.</span>recv<span class="token punctuation">(</span><span class="token number">2048</span><span class="token punctuation">)</span><span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span>
            ChatBox<span class="token punctuation">.</span>insert<span class="token punctuation">(</span><span class="token string">'end'</span><span class="token punctuation">,</span> <span class="token string">'\n'</span><span class="token operator">+</span>content<span class="token operator">+</span><span class="token string">'\n'</span><span class="token punctuation">)</span>
            ChatBox<span class="token punctuation">.</span>see<span class="token punctuation">(</span>tkinter<span class="token punctuation">.</span>END<span class="token punctuation">)</span>  <span class="token comment"># ScrolledText组件方法，自动定位到结尾，否则只有消息在涨，窗口拖动条不动</span>
            ChatBox<span class="token punctuation">.</span>update<span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token comment"># 更新聊天信息窗口，显示新的信息</span>
    threading<span class="token punctuation">.</span>Thread<span class="token punctuation">(</span>target<span class="token operator">=</span>read_server<span class="token punctuation">,</span> args<span class="token operator">=</span><span class="token punctuation">(</span>client<span class="token punctuation">,</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>start<span class="token punctuation">(</span><span class="token punctuation">)</span>

    <span class="token comment">#聊天输入框</span>
    word <span class="token operator">=</span> StringVar<span class="token punctuation">(</span><span class="token punctuation">)</span>
    word<span class="token punctuation">.</span><span class="token builtin">set</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span>
    SentBox <span class="token operator">=</span> Entry<span class="token punctuation">(</span>root<span class="token punctuation">,</span>width<span class="token operator">=</span><span class="token number">140</span><span class="token punctuation">,</span>textvariable<span class="token operator">=</span>word<span class="token punctuation">)</span> <span class="token comment">#建一个输入框</span>
    SentBox<span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">5</span><span class="token punctuation">,</span>y<span class="token operator">=</span><span class="token number">305</span><span class="token punctuation">,</span>width<span class="token operator">=</span><span class="token number">475</span><span class="token punctuation">,</span>height<span class="token operator">=</span><span class="token number">90</span><span class="token punctuation">)</span> <span class="token comment">#设置大小和位置</span>

    <span class="token comment">#发送按钮</span>
    <span class="token keyword">def</span> <span class="token function">sendtext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
        content <span class="token operator">=</span> word<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#获得文本内容</span>
        <span class="token keyword">if</span> content<span class="token operator">==</span><span class="token string">'end'</span><span class="token punctuation">:</span>
            client<span class="token punctuation">.</span>close<span class="token punctuation">(</span><span class="token punctuation">)</span>
        client<span class="token punctuation">.</span>send<span class="token punctuation">(</span>content<span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        word<span class="token punctuation">.</span><span class="token builtin">set</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span> <span class="token comment">#用了一个标记记录点击的状态，不管内容是什么点了就变</span>

    sendButton <span class="token operator">=</span> Button<span class="token punctuation">(</span>root<span class="token punctuation">,</span> text<span class="token operator">=</span><span class="token string">'发 送'</span><span class="token punctuation">,</span> font<span class="token operator">=</span><span class="token punctuation">(</span><span class="token string">'Fangsong'</span><span class="token punctuation">,</span> <span class="token number">18</span><span class="token punctuation">)</span><span class="token punctuation">,</span> bg<span class="token operator">=</span><span class="token string">'white'</span><span class="token punctuation">,</span> command<span class="token operator">=</span>sendtext<span class="token punctuation">)</span>
    sendButton<span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">490</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">308</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">150</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">85</span><span class="token punctuation">)</span>

    root<span class="token punctuation">.</span>mainloop<span class="token punctuation">(</span><span class="token punctuation">)</span>

LoginWindow<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment">#服务端</span>
<span class="token keyword">import</span> socket
<span class="token keyword">import</span> threading
<span class="token keyword">import</span> time

host <span class="token operator">=</span> socket<span class="token punctuation">.</span>gethostname<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#获取当前主机的IP地址</span>
port <span class="token operator">=</span> <span class="token number">9999</span> <span class="token comment">#设置防火墙开放端口</span>
SocketList <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token comment">#存储客户端套接字的列表</span>
TextList <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token comment">#存储聊天记录</span>
Nickname <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token comment">#存储用户呢称</span>
cnt <span class="token operator">=</span> <span class="token number">0</span> <span class="token comment">#当前客户端人数</span>
<span class="token keyword">print</span><span class="token punctuation">(</span>host<span class="token punctuation">)</span>

server <span class="token operator">=</span> socket<span class="token punctuation">.</span>socket<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#创建server对象</span>
server<span class="token punctuation">.</span>bind<span class="token punctuation">(</span><span class="token punctuation">(</span>host<span class="token punctuation">,</span>port<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">#绑定</span>
server<span class="token punctuation">.</span>listen<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#监听</span>
<span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'服务器准备就绪！'</span><span class="token punctuation">)</span>

<span class="token keyword">def</span> <span class="token function">CRC</span><span class="token punctuation">(</span>crc<span class="token punctuation">,</span>poly<span class="token operator">=</span><span class="token string">'11001'</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    test_crc <span class="token operator">=</span> <span class="token builtin">int</span><span class="token punctuation">(</span>crc<span class="token punctuation">,</span><span class="token number">16</span><span class="token punctuation">)</span> <span class="token comment">#将str类型转化成16进制</span>
    poly_crc8 <span class="token operator">=</span> <span class="token builtin">int</span><span class="token punctuation">(</span>poly<span class="token punctuation">,</span><span class="token number">16</span><span class="token punctuation">)</span>
    <span class="token comment"># print(test_crc,poly_crc8)</span>

    <span class="token keyword">for</span> bit <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span><span class="token number">12</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword">if</span> test_crc<span class="token operator">&amp;</span><span class="token number">0x800</span> <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">:</span> <span class="token comment">#最高位是否为1</span>
            test_crc <span class="token operator">&lt;&lt;</span><span class="token operator">=</span> <span class="token number">1</span>
            test_crc <span class="token operator">^</span><span class="token operator">=</span> poly_crc8
        <span class="token keyword">else</span><span class="token punctuation">:</span>
            test_crc <span class="token operator">&lt;&lt;</span><span class="token operator">=</span> <span class="token number">1</span>
        <span class="token keyword">print</span><span class="token punctuation">(</span>test_crc<span class="token punctuation">)</span>
    <span class="token keyword">return</span> <span class="token builtin">hex</span><span class="token punctuation">(</span>test_crc<span class="token punctuation">)</span>

<span class="token comment">#接收一个客户端连接，及其发送来数据</span>
<span class="token keyword">def</span> <span class="token function">read_client</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span>nickname<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">try</span><span class="token punctuation">:</span>
        <span class="token comment">#接受客户端发送来的数据</span>
        <span class="token keyword">return</span> s<span class="token punctuation">.</span>recv<span class="token punctuation">(</span><span class="token number">2048</span><span class="token punctuation">)</span><span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span>
    <span class="token keyword">except</span><span class="token punctuation">:</span>
        <span class="token comment">#客户端异常，连接失败，则删除该socket</span>
        <span class="token comment"># print(str(addr)+'已下线！')</span>
        <span class="token keyword">print</span><span class="token punctuation">(</span>nickname <span class="token operator">+</span> <span class="token string">'已下线！'</span><span class="token punctuation">)</span>
        SocketList<span class="token punctuation">.</span>remove<span class="token punctuation">(</span>s<span class="token punctuation">)</span>
        Nickname<span class="token punctuation">.</span>remove<span class="token punctuation">(</span>nickname<span class="token punctuation">)</span>
        <span class="token keyword">for</span> sock <span class="token keyword">in</span> SocketList<span class="token punctuation">:</span>
            sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'系统消息：'</span> <span class="token operator">+</span> nickname <span class="token operator">+</span> <span class="token string">'已下线！'</span><span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">#多线程：将收到的消息发送给所有客户端</span>
<span class="token keyword">def</span> <span class="token function">send_client</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span>nickname<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">try</span><span class="token punctuation">:</span>
        <span class="token comment"># s.send((','.join(Nickname)).encode('utf-8')) #将用户列表发送给各客户端</span>
        <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
            content <span class="token operator">=</span> read_client<span class="token punctuation">(</span>s<span class="token punctuation">,</span>nickname<span class="token punctuation">)</span> <span class="token comment">#客户端消息</span>
            <span class="token keyword">if</span> content <span class="token keyword">is</span> <span class="token boolean">None</span><span class="token punctuation">:</span> <span class="token comment">#如果没有结束循环</span>
                <span class="token keyword">break</span>
            <span class="token keyword">else</span><span class="token punctuation">:</span> <span class="token comment">#如果有将消息保存到历史记录</span>
                <span class="token comment"># TextList.append(str(addr)+': '+content)</span>
                TextList<span class="token punctuation">.</span>append<span class="token punctuation">(</span>nickname <span class="token operator">+</span> <span class="token string">': '</span> <span class="token operator">+</span> content<span class="token punctuation">)</span>
            <span class="token comment">#将一个客户端发送过来的数据广播给其他客户端</span>
            <span class="token keyword">for</span> sock <span class="token keyword">in</span> SocketList<span class="token punctuation">:</span>
                <span class="token comment"># sock.send((str(addr)+': '+content).encode('utf-8'))</span>
                sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span>nickname <span class="token operator">+</span> <span class="token string">': '</span> <span class="token operator">+</span> content<span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

            data <span class="token operator">=</span> CRC<span class="token punctuation">(</span>content<span class="token punctuation">)</span>
            <span class="token keyword">for</span> sock <span class="token keyword">in</span> SocketList<span class="token punctuation">:</span>
                <span class="token comment"># sock.send((str(addr)+': '+content).encode('utf-8'))</span>
                sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'Teacher: '</span> <span class="token operator">+</span> data<span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">except</span> Exception <span class="token keyword">as</span> e<span class="token punctuation">:</span>
        <span class="token comment"># print(repr())</span>
        <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'广播未成功！'</span><span class="token punctuation">)</span>

QianYan <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'你好呀！今天我们一起来学习SW。'</span><span class="token punctuation">,</span>
           <span class="token string">'可靠传输机制是为了使数据可以正确稳定的传输和接收而制定的规则。'</span><span class="token punctuation">,</span>
           <span class="token string">'流量控制是数据链路层的一种功能，流量控制对数据链路上的帧的发送速率进行控制，以使接收方有足够的缓冲空间来接受每个帧。'</span><span class="token punctuation">,</span>
           <span class="token string">'流量控制的基本方法是由接收方控制发送方发送数据的速率。'</span><span class="token punctuation">,</span>
           <span class="token string">'常见的流量控制方式有两种：`停止-等待协议、滑动窗口协议'</span><span class="token punctuation">,</span>
           <span class="token string">'那么，让我们开始体验停止-等待协议SW的魅力吧！'</span><span class="token punctuation">,</span>
           <span class="token string">'\n\n请输入十六进制数据'</span><span class="token punctuation">]</span>

<span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
    client<span class="token punctuation">,</span>addr <span class="token operator">=</span> server<span class="token punctuation">.</span>accept<span class="token punctuation">(</span><span class="token punctuation">)</span>
    SocketList<span class="token punctuation">.</span>append<span class="token punctuation">(</span>client<span class="token punctuation">)</span>

    nickname <span class="token operator">=</span> client<span class="token punctuation">.</span>recv<span class="token punctuation">(</span><span class="token number">2048</span><span class="token punctuation">)</span><span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span>
    <span class="token comment"># print(str(addr)+'已加入！')</span>

    <span class="token keyword">if</span> nickname <span class="token keyword">in</span> Nickname<span class="token punctuation">:</span>
        i <span class="token operator">=</span> <span class="token number">1</span>
        <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
            <span class="token keyword">if</span> nickname<span class="token operator">+</span><span class="token builtin">str</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span> <span class="token keyword">in</span> Nickname<span class="token punctuation">:</span>
                i <span class="token operator">=</span> i<span class="token operator">+</span><span class="token number">1</span>
            <span class="token keyword">else</span><span class="token punctuation">:</span>
                nickname <span class="token operator">=</span> nickname <span class="token operator">+</span> <span class="token builtin">str</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span>
                <span class="token keyword">break</span>
    Nickname<span class="token punctuation">.</span>append<span class="token punctuation">(</span>nickname<span class="token punctuation">)</span>
    <span class="token keyword">print</span><span class="token punctuation">(</span>nickname <span class="token operator">+</span> <span class="token string">'已加入！'</span><span class="token punctuation">)</span>

    <span class="token keyword">for</span> sock <span class="token keyword">in</span> SocketList<span class="token punctuation">:</span>
        <span class="token keyword">for</span> i <span class="token keyword">in</span> QianYan<span class="token punctuation">:</span>
            sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'Teacher: '</span> <span class="token operator">+</span> i<span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
            time<span class="token punctuation">.</span>sleep<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span>

    cnt <span class="token operator">=</span> cnt <span class="token operator">+</span> <span class="token number">1</span>

    <span class="token comment">#每当有客户连接后，就启动一个线程为其服务</span>
    <span class="token comment">#加入线程中跑，加入函数为send_client，参数为client,nickname</span>
    threading<span class="token punctuation">.</span>Thread<span class="token punctuation">(</span>target<span class="token operator">=</span>send_client<span class="token punctuation">,</span> args<span class="token operator">=</span><span class="token punctuation">(</span>client<span class="token punctuation">,</span>nickname<span class="token punctuation">,</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>start<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h3 id="0-65-1"><a href="#0-65-1" class="headerlink" title="0.65"></a><strong>0.65</strong></h3><p><strong>作用：早上灵光一现，以为CRC是取模了……</strong></p>
<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment">#服务端</span>
<span class="token keyword">import</span> socket
<span class="token keyword">import</span> threading
<span class="token keyword">import</span> time

host <span class="token operator">=</span> socket<span class="token punctuation">.</span>gethostname<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#获取当前主机的IP地址</span>
port <span class="token operator">=</span> <span class="token number">9999</span> <span class="token comment">#设置防火墙开放端口</span>
SocketList <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token comment">#存储客户端套接字的列表</span>
TextList <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token comment">#存储聊天记录</span>
Nickname <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token comment">#存储用户呢称</span>
cnt <span class="token operator">=</span> <span class="token number">0</span> <span class="token comment">#当前客户端人数</span>
<span class="token keyword">print</span><span class="token punctuation">(</span>host<span class="token punctuation">)</span>

server <span class="token operator">=</span> socket<span class="token punctuation">.</span>socket<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#创建server对象</span>
server<span class="token punctuation">.</span>bind<span class="token punctuation">(</span><span class="token punctuation">(</span>host<span class="token punctuation">,</span>port<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">#绑定</span>
server<span class="token punctuation">.</span>listen<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#监听</span>
<span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'服务器准备就绪！'</span><span class="token punctuation">)</span>

<span class="token keyword">def</span> <span class="token function">DEC</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span><span class="token punctuation">:</span>
    s <span class="token operator">=</span> data
    d <span class="token operator">=</span> <span class="token number">0</span>
    <span class="token keyword">while</span> s<span class="token punctuation">:</span>
        d <span class="token operator">=</span> d<span class="token operator">*</span><span class="token number">2</span> <span class="token operator">+</span> <span class="token punctuation">(</span><span class="token builtin">ord</span><span class="token punctuation">(</span>s<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token builtin">ord</span><span class="token punctuation">(</span><span class="token string">'0'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        s <span class="token operator">=</span> s<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">:</span><span class="token punctuation">]</span>
    <span class="token keyword">return</span> d

<span class="token keyword">def</span> <span class="token function">CRC</span><span class="token punctuation">(</span>crc<span class="token punctuation">,</span>poly<span class="token operator">=</span><span class="token string">'11001'</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    p <span class="token operator">=</span> DEC<span class="token punctuation">(</span>poly<span class="token punctuation">)</span>
    c <span class="token operator">=</span> DEC<span class="token punctuation">(</span>crc<span class="token operator">+</span><span class="token string">'0000'</span><span class="token punctuation">)</span>
    <span class="token keyword">print</span><span class="token punctuation">(</span>p<span class="token punctuation">,</span>c<span class="token punctuation">)</span>
    res <span class="token operator">=</span> c<span class="token operator">%</span>p
    <span class="token keyword">return</span> res

<span class="token comment">#接收一个客户端连接，及其发送来数据</span>
<span class="token keyword">def</span> <span class="token function">read_client</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span>nickname<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">try</span><span class="token punctuation">:</span>
        <span class="token comment">#接受客户端发送来的数据</span>
        <span class="token keyword">return</span> s<span class="token punctuation">.</span>recv<span class="token punctuation">(</span><span class="token number">2048</span><span class="token punctuation">)</span><span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span>
    <span class="token keyword">except</span><span class="token punctuation">:</span>
        <span class="token comment">#客户端异常，连接失败，则删除该socket</span>
        <span class="token comment"># print(str(addr)+'已下线！')</span>
        <span class="token keyword">print</span><span class="token punctuation">(</span>nickname <span class="token operator">+</span> <span class="token string">'已下线！'</span><span class="token punctuation">)</span>
        SocketList<span class="token punctuation">.</span>remove<span class="token punctuation">(</span>s<span class="token punctuation">)</span>
        Nickname<span class="token punctuation">.</span>remove<span class="token punctuation">(</span>nickname<span class="token punctuation">)</span>
        <span class="token keyword">for</span> sock <span class="token keyword">in</span> SocketList<span class="token punctuation">:</span>
            sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'系统消息：'</span> <span class="token operator">+</span> nickname <span class="token operator">+</span> <span class="token string">'已下线！'</span><span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">#多线程：将收到的消息发送给所有客户端</span>
<span class="token keyword">def</span> <span class="token function">send_client</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span>nickname<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">try</span><span class="token punctuation">:</span>
        <span class="token comment"># s.send((','.join(Nickname)).encode('utf-8')) #将用户列表发送给各客户端</span>
        <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
            content <span class="token operator">=</span> read_client<span class="token punctuation">(</span>s<span class="token punctuation">,</span>nickname<span class="token punctuation">)</span> <span class="token comment">#客户端消息</span>
            <span class="token keyword">if</span> content <span class="token keyword">is</span> <span class="token boolean">None</span><span class="token punctuation">:</span> <span class="token comment">#如果没有结束循环</span>
                <span class="token keyword">break</span>
            <span class="token keyword">else</span><span class="token punctuation">:</span> <span class="token comment">#如果有将消息保存到历史记录</span>
                <span class="token comment"># TextList.append(str(addr)+': '+content)</span>
                TextList<span class="token punctuation">.</span>append<span class="token punctuation">(</span>nickname <span class="token operator">+</span> <span class="token string">': '</span> <span class="token operator">+</span> content<span class="token punctuation">)</span>
            <span class="token comment">#将一个客户端发送过来的数据广播给其他客户端</span>
            <span class="token keyword">for</span> sock <span class="token keyword">in</span> SocketList<span class="token punctuation">:</span>
                <span class="token comment"># sock.send((str(addr)+': '+content).encode('utf-8'))</span>
                sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span>nickname <span class="token operator">+</span> <span class="token string">': '</span> <span class="token operator">+</span> content<span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

            data <span class="token operator">=</span> CRC<span class="token punctuation">(</span>content<span class="token punctuation">)</span>
            <span class="token keyword">if</span> data<span class="token operator">==</span><span class="token number">0</span><span class="token punctuation">:</span>
                word <span class="token operator">=</span> <span class="token string">'发送帧没问题。'</span>
            <span class="token keyword">else</span><span class="token punctuation">:</span>
                word <span class="token operator">=</span> <span class="token string">'发送帧有问题。'</span>

            <span class="token keyword">for</span> sock <span class="token keyword">in</span> SocketList<span class="token punctuation">:</span>
                <span class="token comment"># sock.send((str(addr)+': '+content).encode('utf-8'))</span>
                sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'Teacher: '</span> <span class="token operator">+</span> word<span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">except</span> Exception <span class="token keyword">as</span> e<span class="token punctuation">:</span>
        <span class="token comment"># print(repr())</span>
        <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'广播未成功！'</span><span class="token punctuation">)</span>

QianYan <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'你好呀！今天我们一起来学习SW。'</span><span class="token punctuation">,</span>
           <span class="token string">'可靠传输机制是为了使数据可以正确稳定的传输和接收而制定的规则。'</span><span class="token punctuation">,</span>
           <span class="token string">'流量控制是数据链路层的一种功能，流量控制对数据链路上的帧的发送速率进行控制，以使接收方有足够的缓冲空间来接受每个帧。'</span><span class="token punctuation">,</span>
           <span class="token string">'流量控制的基本方法是由接收方控制发送方发送数据的速率。'</span><span class="token punctuation">,</span>
           <span class="token string">'常见的流量控制方式有两种：`停止-等待协议、滑动窗口协议'</span><span class="token punctuation">,</span>
           <span class="token string">'那么，让我们开始体验停止-等待协议SW的魅力吧！'</span><span class="token punctuation">,</span>
           <span class="token string">'\n\n请输入十六进制数据'</span><span class="token punctuation">]</span>

<span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
    client<span class="token punctuation">,</span>addr <span class="token operator">=</span> server<span class="token punctuation">.</span>accept<span class="token punctuation">(</span><span class="token punctuation">)</span>
    SocketList<span class="token punctuation">.</span>append<span class="token punctuation">(</span>client<span class="token punctuation">)</span>

    nickname <span class="token operator">=</span> client<span class="token punctuation">.</span>recv<span class="token punctuation">(</span><span class="token number">2048</span><span class="token punctuation">)</span><span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span>
    <span class="token comment"># print(str(addr)+'已加入！')</span>

    <span class="token keyword">if</span> nickname <span class="token keyword">in</span> Nickname<span class="token punctuation">:</span>
        i <span class="token operator">=</span> <span class="token number">1</span>
        <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
            <span class="token keyword">if</span> nickname<span class="token operator">+</span><span class="token builtin">str</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span> <span class="token keyword">in</span> Nickname<span class="token punctuation">:</span>
                i <span class="token operator">=</span> i<span class="token operator">+</span><span class="token number">1</span>
            <span class="token keyword">else</span><span class="token punctuation">:</span>
                nickname <span class="token operator">=</span> nickname <span class="token operator">+</span> <span class="token builtin">str</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span>
                <span class="token keyword">break</span>
    Nickname<span class="token punctuation">.</span>append<span class="token punctuation">(</span>nickname<span class="token punctuation">)</span>
    <span class="token keyword">print</span><span class="token punctuation">(</span>nickname <span class="token operator">+</span> <span class="token string">'已加入！'</span><span class="token punctuation">)</span>

    <span class="token keyword">for</span> sock <span class="token keyword">in</span> SocketList<span class="token punctuation">:</span>
        <span class="token keyword">for</span> i <span class="token keyword">in</span> QianYan<span class="token punctuation">:</span>
            sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'Teacher: '</span> <span class="token operator">+</span> i<span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
            time<span class="token punctuation">.</span>sleep<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span>

    cnt <span class="token operator">=</span> cnt <span class="token operator">+</span> <span class="token number">1</span>

    <span class="token comment">#每当有客户连接后，就启动一个线程为其服务</span>
    <span class="token comment">#加入线程中跑，加入函数为send_client，参数为client,nickname</span>
    threading<span class="token punctuation">.</span>Thread<span class="token punctuation">(</span>target<span class="token operator">=</span>send_client<span class="token punctuation">,</span> args<span class="token operator">=</span><span class="token punctuation">(</span>client<span class="token punctuation">,</span>nickname<span class="token punctuation">,</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>start<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment">#客户端</span>
<span class="token keyword">import</span> socket
<span class="token keyword">import</span> threading
<span class="token keyword">from</span> tkinter <span class="token keyword">import</span> <span class="token operator">*</span>
<span class="token keyword">import</span> tkinter<span class="token punctuation">.</span>messagebox <span class="token comment">#弹窗库</span>
<span class="token keyword">from</span> tkinter <span class="token keyword">import</span> scrolledtext  <span class="token comment">#滚动文本框</span>

server_host <span class="token operator">=</span> socket<span class="token punctuation">.</span>gethostname<span class="token punctuation">(</span><span class="token punctuation">)</span>
server_port <span class="token operator">=</span> <span class="token number">9999</span>

client <span class="token operator">=</span> socket<span class="token punctuation">.</span>socket<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#创建socket对象</span>
<span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'Connecting......'</span><span class="token punctuation">)</span>


<span class="token comment">#登入窗口：输入呢称</span>
<span class="token keyword">def</span> <span class="token function">LoginWindow</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    root <span class="token operator">=</span> Tk<span class="token punctuation">(</span><span class="token punctuation">)</span>
    root<span class="token punctuation">.</span>title<span class="token punctuation">(</span><span class="token string">'一起来聊天 · 登录'</span><span class="token punctuation">)</span> <span class="token comment">#窗口标题</span>
    root<span class="token punctuation">.</span>geometry<span class="token punctuation">(</span><span class="token string">'300x150'</span><span class="token punctuation">)</span> <span class="token comment">#窗口大小</span>
    root<span class="token punctuation">.</span>geometry<span class="token punctuation">(</span><span class="token string">'+500+300'</span><span class="token punctuation">)</span> <span class="token comment">#改变窗体位置（‘+横坐标+纵坐标’）</span>
    nickname <span class="token operator">=</span> StringVar<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#昵称变量（对象）:在使用界面编程的时候，有些时候是需要跟踪变量的值的变化，以保证值的变更随时可以显示在界面上</span>
    root<span class="token punctuation">.</span>resizable<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token comment">#将窗口大小设置为不可变</span>

    <span class="token comment">#登录函数（检查用户名是否为空，以及长度）</span>
    <span class="token keyword">def</span> <span class="token function">Login_in</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
        name <span class="token operator">=</span> nickname<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#????</span>
        <span class="token keyword">if</span> <span class="token keyword">not</span> name<span class="token punctuation">:</span>
            tkinter<span class="token punctuation">.</span>messagebox<span class="token punctuation">.</span>showwarning<span class="token punctuation">(</span><span class="token string">'Warning'</span><span class="token punctuation">,</span> message<span class="token operator">=</span><span class="token string">'用户名为空！'</span><span class="token punctuation">)</span> <span class="token comment">#消息警告框</span>
        <span class="token keyword">elif</span> <span class="token builtin">len</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span> <span class="token operator">></span> <span class="token number">10</span><span class="token punctuation">:</span>
            tkinter<span class="token punctuation">.</span>messagebox<span class="token punctuation">.</span>showwarning<span class="token punctuation">(</span><span class="token string">'Warning'</span><span class="token punctuation">,</span> message<span class="token operator">=</span><span class="token string">'用户名过长！最多为十个字符！'</span><span class="token punctuation">)</span>
        <span class="token keyword">else</span><span class="token punctuation">:</span>
            root<span class="token punctuation">.</span>destroy<span class="token punctuation">(</span><span class="token punctuation">)</span>
            client<span class="token punctuation">.</span>connect<span class="token punctuation">(</span><span class="token punctuation">(</span>server_host<span class="token punctuation">,</span> server_port<span class="token punctuation">)</span><span class="token punctuation">)</span>  <span class="token comment"># 连接服务端，指定主机和端口</span>
            <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'Connecting is successful!'</span><span class="token punctuation">)</span>
            client<span class="token punctuation">.</span>send<span class="token punctuation">(</span>name<span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>  <span class="token comment"># 传递用户昵称</span>
            ChatRoom<span class="token punctuation">(</span>name<span class="token punctuation">)</span>  <span class="token comment"># 打开聊天窗口</span>

    <span class="token comment">#登录按钮、输入提示标签、输入框</span>
    Button<span class="token punctuation">(</span>root<span class="token punctuation">,</span> text<span class="token operator">=</span><span class="token string">"登录"</span><span class="token punctuation">,</span> command<span class="token operator">=</span>Login_in<span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">8</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">90</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">35</span><span class="token punctuation">)</span>
    Label<span class="token punctuation">(</span>root<span class="token punctuation">,</span> text<span class="token operator">=</span><span class="token string">'请输入昵称'</span><span class="token punctuation">,</span> font<span class="token operator">=</span><span class="token punctuation">(</span><span class="token string">'Fangsong'</span><span class="token punctuation">,</span> <span class="token number">12</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">10</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">20</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">50</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">80</span><span class="token punctuation">)</span>
    Entry<span class="token punctuation">(</span>root<span class="token punctuation">,</span> textvariable<span class="token operator">=</span>nickname<span class="token punctuation">,</span> font<span class="token operator">=</span><span class="token punctuation">(</span><span class="token string">'Fangsong'</span><span class="token punctuation">,</span> <span class="token number">11</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">30</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">30</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">180</span><span class="token punctuation">)</span>

    root<span class="token punctuation">.</span>mainloop<span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">#聊天窗口</span>
<span class="token keyword">def</span> <span class="token function">ChatRoom</span><span class="token punctuation">(</span>nickname<span class="token punctuation">)</span><span class="token punctuation">:</span>
    root <span class="token operator">=</span> Tk<span class="token punctuation">(</span><span class="token punctuation">)</span>
    root<span class="token punctuation">.</span>geometry<span class="token punctuation">(</span><span class="token string">'650x400'</span><span class="token punctuation">)</span>  <span class="token comment"># 窗口大小</span>
    root<span class="token punctuation">.</span>resizable<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>  <span class="token comment"># 将窗口大小设置为不可变</span>
    root<span class="token punctuation">.</span>geometry<span class="token punctuation">(</span><span class="token string">'+500+300'</span><span class="token punctuation">)</span>  <span class="token comment"># 改变窗体位置（‘+横坐标+纵坐标’）</span>

    <span class="token comment"># content = client.recv(2048).decode('utf-8')</span>
    <span class="token comment"># if content != 'No message.':</span>
    <span class="token comment">#     past_text = content + '\n------以上是历史消息------\n'</span>

    <span class="token comment"># 从服务器端获取当前用户列表</span>
    <span class="token comment"># UserList = []</span>
    <span class="token comment"># UserList = client.recv(2048).decode('utf-8').split(',')</span>
    <span class="token comment"># UserList.insert(0, '------当前用户列表------')</span>

    <span class="token comment"># 窗口标题</span>
    <span class="token comment"># nickname = UserList[len(UserList)-1]</span>
    root<span class="token punctuation">.</span>title<span class="token punctuation">(</span><span class="token string">'一起来聊天 · '</span> <span class="token operator">+</span> nickname<span class="token punctuation">)</span>

    <span class="token comment"># name_text = StringVar()</span>
    <span class="token comment"># name_text.set(UserList)  # 用户列表文本设置</span>
    <span class="token comment"># listbox1 = Listbox(root, listvariable=name_text)  # 用户列表，使用Listbox组件</span>
    <span class="token comment"># listbox1.place(x=5, y=0, width=500, height=400)</span>

    img_png <span class="token operator">=</span> PhotoImage<span class="token punctuation">(</span><span class="token builtin">file</span><span class="token operator">=</span><span class="token string">'QQ图片20220901201640.png'</span><span class="token punctuation">)</span>
    label_img <span class="token operator">=</span> Label<span class="token punctuation">(</span>root<span class="token punctuation">,</span> image<span class="token operator">=</span>img_png<span class="token punctuation">)</span>
    label_img<span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">400</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">350</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">300</span><span class="token punctuation">)</span>

    <span class="token comment">#聊天界面</span>
    <span class="token comment"># content = client.recv(2048).decode('utf-8')</span>
    ChatBox <span class="token operator">=</span> scrolledtext<span class="token punctuation">.</span>ScrolledText<span class="token punctuation">(</span>root<span class="token punctuation">)</span>  <span class="token comment"># 聊天信息窗口，使用ScrolledText组件制作</span>
    ChatBox<span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">5</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">470</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">300</span><span class="token punctuation">)</span>
    <span class="token comment"># ChatBox.pack()</span>
    <span class="token comment"># ChatBox.insert('end',content)</span>

    <span class="token keyword">def</span> <span class="token function">read_server</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
            content <span class="token operator">=</span> c<span class="token punctuation">.</span>recv<span class="token punctuation">(</span><span class="token number">2048</span><span class="token punctuation">)</span><span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span>
            ChatBox<span class="token punctuation">.</span>insert<span class="token punctuation">(</span><span class="token string">'end'</span><span class="token punctuation">,</span> <span class="token string">'\n'</span><span class="token operator">+</span>content<span class="token operator">+</span><span class="token string">'\n'</span><span class="token punctuation">)</span>
            ChatBox<span class="token punctuation">.</span>see<span class="token punctuation">(</span>tkinter<span class="token punctuation">.</span>END<span class="token punctuation">)</span>  <span class="token comment"># ScrolledText组件方法，自动定位到结尾，否则只有消息在涨，窗口拖动条不动</span>
            ChatBox<span class="token punctuation">.</span>update<span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token comment"># 更新聊天信息窗口，显示新的信息</span>
    threading<span class="token punctuation">.</span>Thread<span class="token punctuation">(</span>target<span class="token operator">=</span>read_server<span class="token punctuation">,</span> args<span class="token operator">=</span><span class="token punctuation">(</span>client<span class="token punctuation">,</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>start<span class="token punctuation">(</span><span class="token punctuation">)</span>

    <span class="token comment">#聊天输入框</span>
    word <span class="token operator">=</span> StringVar<span class="token punctuation">(</span><span class="token punctuation">)</span>
    word<span class="token punctuation">.</span><span class="token builtin">set</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span>
    SentBox <span class="token operator">=</span> Entry<span class="token punctuation">(</span>root<span class="token punctuation">,</span>width<span class="token operator">=</span><span class="token number">140</span><span class="token punctuation">,</span>textvariable<span class="token operator">=</span>word<span class="token punctuation">)</span> <span class="token comment">#建一个输入框</span>
    SentBox<span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">5</span><span class="token punctuation">,</span>y<span class="token operator">=</span><span class="token number">305</span><span class="token punctuation">,</span>width<span class="token operator">=</span><span class="token number">475</span><span class="token punctuation">,</span>height<span class="token operator">=</span><span class="token number">90</span><span class="token punctuation">)</span> <span class="token comment">#设置大小和位置</span>

    <span class="token comment">#发送按钮</span>
    <span class="token keyword">def</span> <span class="token function">sendtext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
        content <span class="token operator">=</span> word<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#获得文本内容</span>
        <span class="token keyword">if</span> content<span class="token operator">==</span><span class="token string">'end'</span><span class="token punctuation">:</span>
            client<span class="token punctuation">.</span>close<span class="token punctuation">(</span><span class="token punctuation">)</span>
        client<span class="token punctuation">.</span>send<span class="token punctuation">(</span>content<span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        word<span class="token punctuation">.</span><span class="token builtin">set</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span> <span class="token comment">#用了一个标记记录点击的状态，不管内容是什么点了就变</span>

    sendButton <span class="token operator">=</span> Button<span class="token punctuation">(</span>root<span class="token punctuation">,</span> text<span class="token operator">=</span><span class="token string">'发 送'</span><span class="token punctuation">,</span> font<span class="token operator">=</span><span class="token punctuation">(</span><span class="token string">'Fangsong'</span><span class="token punctuation">,</span> <span class="token number">18</span><span class="token punctuation">)</span><span class="token punctuation">,</span> bg<span class="token operator">=</span><span class="token string">'white'</span><span class="token punctuation">,</span> command<span class="token operator">=</span>sendtext<span class="token punctuation">)</span>
    sendButton<span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">490</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">308</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">150</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">85</span><span class="token punctuation">)</span>

    root<span class="token punctuation">.</span>mainloop<span class="token punctuation">(</span><span class="token punctuation">)</span>

LoginWindow<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h3 id="0-7"><a href="#0-7" class="headerlink" title="0.7"></a>0.7</h3><p><strong>作用：拿的网上的CRC但感觉还是错的……</strong></p>
<blockquote>
<p><a target="_blank" rel="noopener" href="https://cn.bing.com/search?q=crc%E5%8E%9F%E7%90%86Python&qs=n&form=QBRE&sp=-1&pq=crc%E5%8E%9F%E7%90%86python&sc=0-11&sk=&cvid=66D0F3FB7AC54F3683ABFEB1122DA0BF&ghsh=0&ghacc=0&ghpl=">crc原理Python - Search (bing.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/smallfox233/article/details/111242813">https://blog.csdn.net/smallfox233/article/details/111242813</a></p>
</blockquote>
<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment">#服务端</span>
<span class="token keyword">import</span> socket
<span class="token keyword">import</span> threading
<span class="token keyword">import</span> time

host <span class="token operator">=</span> socket<span class="token punctuation">.</span>gethostname<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#获取当前主机的IP地址</span>
port <span class="token operator">=</span> <span class="token number">9999</span> <span class="token comment">#设置防火墙开放端口</span>
SocketList <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token comment">#存储客户端套接字的列表</span>
TextList <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token comment">#存储聊天记录</span>
Nickname <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token comment">#存储用户呢称</span>
cnt <span class="token operator">=</span> <span class="token number">0</span> <span class="token comment">#当前客户端人数</span>
<span class="token keyword">print</span><span class="token punctuation">(</span>host<span class="token punctuation">)</span>

server <span class="token operator">=</span> socket<span class="token punctuation">.</span>socket<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#创建server对象</span>
server<span class="token punctuation">.</span>bind<span class="token punctuation">(</span><span class="token punctuation">(</span>host<span class="token punctuation">,</span>port<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">#绑定</span>
server<span class="token punctuation">.</span>listen<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#监听</span>
<span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'服务器准备就绪！'</span><span class="token punctuation">)</span>

<span class="token keyword">def</span> <span class="token function">TurnBin</span><span class="token punctuation">(</span>expression<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token triple-quoted-string string">'''将生成多项式转换为二进制字符串输出'''</span>
    <span class="token comment"># 输入数据处理</span>
    expression <span class="token operator">=</span> expression<span class="token punctuation">.</span>upper<span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token comment"># 大写转换</span>
    lis <span class="token operator">=</span> <span class="token builtin">list</span><span class="token punctuation">(</span>expression<span class="token punctuation">.</span>split<span class="token punctuation">(</span><span class="token string">"+"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>  <span class="token comment"># 以加号为标志进行分割</span>
    string <span class="token operator">=</span> lis<span class="token punctuation">[</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span>  <span class="token comment"># 多项式末尾的数字1</span>
    <span class="token keyword">del</span> lis<span class="token punctuation">[</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span>
    lis <span class="token operator">=</span> lis<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span>  <span class="token comment"># 倒序</span>
    <span class="token comment">##    print(lis)</span>
    <span class="token comment"># 二进制转换</span>
    <span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span><span class="token builtin">len</span><span class="token punctuation">(</span>lis<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword">if</span> <span class="token builtin">len</span><span class="token punctuation">(</span>string<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token builtin">int</span><span class="token punctuation">(</span>lis<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">:</span>  <span class="token comment"># 满足位数与变量的数字相同时</span>
            string <span class="token operator">+=</span> <span class="token string">"1"</span>
        <span class="token keyword">else</span><span class="token punctuation">:</span>
            <span class="token keyword">for</span> j <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">(</span>lis<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token builtin">len</span><span class="token punctuation">(</span>string<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">:</span>  <span class="token comment"># 用0补全相差的位数</span>
                string <span class="token operator">+=</span> <span class="token string">"0"</span>
            string <span class="token operator">+=</span> <span class="token string">"1"</span>
    <span class="token keyword">return</span> string<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span>


<span class="token keyword">def</span> <span class="token function">XOR</span><span class="token punctuation">(</span>string1<span class="token punctuation">,</span> string2<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token triple-quoted-string string">'''将两个二进制串进行异或操作，不同为1'''</span>
    result <span class="token operator">=</span> <span class="token string">""</span>
    <span class="token comment"># 输入数据处理</span>
    <span class="token keyword">if</span> <span class="token builtin">len</span><span class="token punctuation">(</span>string1<span class="token punctuation">)</span> <span class="token operator">&lt;</span> <span class="token builtin">len</span><span class="token punctuation">(</span>string2<span class="token punctuation">)</span><span class="token punctuation">:</span>  <span class="token comment"># 若前者的位数不足时</span>
        <span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span><span class="token builtin">len</span><span class="token punctuation">(</span>string2<span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token builtin">len</span><span class="token punctuation">(</span>string1<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">:</span>  <span class="token comment"># 对string1的首位补0</span>
            string1 <span class="token operator">=</span> <span class="token string">"0"</span> <span class="token operator">+</span> string1
    <span class="token keyword">if</span> <span class="token builtin">len</span><span class="token punctuation">(</span>string1<span class="token punctuation">)</span> <span class="token operator">></span> <span class="token builtin">len</span><span class="token punctuation">(</span>string2<span class="token punctuation">)</span><span class="token punctuation">:</span>  <span class="token comment"># 若后者的位数不足时</span>
        <span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span><span class="token builtin">len</span><span class="token punctuation">(</span>string1<span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token builtin">len</span><span class="token punctuation">(</span>string2<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">:</span>  <span class="token comment"># 对string2的首位补0</span>
            string2 <span class="token operator">=</span> <span class="token string">"0"</span> <span class="token operator">+</span> string2
    <span class="token comment">##    print(string1,string2)</span>
    <span class="token comment"># 异或计算</span>
    <span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span><span class="token builtin">len</span><span class="token punctuation">(</span>string1<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword">if</span> string1<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">!=</span> string2<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">:</span>
            result <span class="token operator">+=</span> <span class="token string">"1"</span>
        <span class="token keyword">else</span><span class="token punctuation">:</span>
            result <span class="token operator">+=</span> <span class="token string">"0"</span>
    <span class="token comment">##    print(result)</span>
    <span class="token comment"># 输出数据处理</span>
    <span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span><span class="token builtin">len</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">:</span>  <span class="token comment"># 消除异或结果中的无效0</span>
        <span class="token keyword">if</span> result<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">==</span> <span class="token string">"1"</span><span class="token punctuation">:</span>  <span class="token comment"># 找到第一个有效数据时</span>
            <span class="token keyword">return</span> result<span class="token punctuation">[</span>i<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token punctuation">]</span>
    <span class="token keyword">return</span> result

<span class="token keyword">def</span> <span class="token function">CRC</span><span class="token punctuation">(</span>string<span class="token punctuation">,</span> expression<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token triple-quoted-string string">'''产生CRC校验码'''</span>
    crc <span class="token operator">=</span> <span class="token string">""</span>  <span class="token comment"># 最终的crc校验码</span>
    <span class="token comment"># 输入数据处理</span>
    bin_expression <span class="token operator">=</span> TurnBin<span class="token punctuation">(</span>expression<span class="token punctuation">)</span>  <span class="token comment"># 转换为二进制串</span>
    <span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span><span class="token builtin">len</span><span class="token punctuation">(</span>bin_expression<span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">:</span>  <span class="token comment"># 在二进制串末尾补0</span>
        string <span class="token operator">+=</span> <span class="token string">"0"</span>
    <span class="token comment">##    print(string,bin_expression)</span>
    <span class="token comment"># CRC计算</span>
    <span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span><span class="token builtin">len</span><span class="token punctuation">(</span>string<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">:</span>  <span class="token comment"># 遍历被除数二进制串</span>
        crc <span class="token operator">+=</span> string<span class="token punctuation">[</span>i<span class="token punctuation">]</span>
        <span class="token keyword">if</span> <span class="token builtin">len</span><span class="token punctuation">(</span>crc<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token builtin">len</span><span class="token punctuation">(</span>bin_expression<span class="token punctuation">)</span><span class="token punctuation">:</span>  <span class="token comment"># 当位数足够异或计算时</span>
            crc <span class="token operator">=</span> XOR<span class="token punctuation">(</span>crc<span class="token punctuation">,</span> bin_expression<span class="token punctuation">)</span>
    <span class="token comment">##    print(crc)</span>
    <span class="token comment"># 输出数据处理</span>
    <span class="token keyword">if</span> <span class="token builtin">len</span><span class="token punctuation">(</span>crc<span class="token punctuation">)</span> <span class="token operator">&lt;</span> <span class="token builtin">len</span><span class="token punctuation">(</span>bin_expression<span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">:</span>  <span class="token comment"># 当crc位数不足时</span>
        <span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span><span class="token builtin">len</span><span class="token punctuation">(</span>bin_expression<span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token builtin">len</span><span class="token punctuation">(</span>crc<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">:</span>  <span class="token comment"># 在首部补0</span>
            crc <span class="token operator">=</span> <span class="token string">"0"</span> <span class="token operator">+</span> crc
    <span class="token keyword">if</span> <span class="token builtin">len</span><span class="token punctuation">(</span>crc<span class="token punctuation">)</span> <span class="token operator">></span> <span class="token builtin">len</span><span class="token punctuation">(</span>bin_expression<span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">:</span>  <span class="token comment"># 当crc位数过多时</span>
        crc <span class="token operator">=</span> crc<span class="token punctuation">[</span><span class="token builtin">len</span><span class="token punctuation">(</span>crc<span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token builtin">len</span><span class="token punctuation">(</span>bin_expression<span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token punctuation">]</span>  <span class="token comment"># 切片，消除首部多余的0</span>
    <span class="token keyword">return</span> crc

<span class="token keyword">def</span> <span class="token function">CheckCRC</span><span class="token punctuation">(</span>string<span class="token punctuation">,</span> expression<span class="token operator">=</span><span class="token string">'x4+x3+1'</span><span class="token punctuation">)</span><span class="token punctuation">:</span>  <span class="token comment"># 检测传输数据是否正确，并打印结果</span>
    <span class="token comment"># 输入数据处理</span>
    bin_expression <span class="token operator">=</span> TurnBin<span class="token punctuation">(</span>expression<span class="token punctuation">)</span>  <span class="token comment"># 转换为二进制串</span>
    right_crc <span class="token operator">=</span> string<span class="token punctuation">[</span><span class="token builtin">len</span><span class="token punctuation">(</span>string<span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token builtin">len</span><span class="token punctuation">(</span>bin_expression<span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token punctuation">]</span>  <span class="token comment"># 原数据末尾的crc校验码</span>
    <span class="token comment"># CRC计算</span>
    crc <span class="token operator">=</span> CRC<span class="token punctuation">(</span>string<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token builtin">len</span><span class="token punctuation">(</span>string<span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token builtin">len</span><span class="token punctuation">(</span>bin_expression<span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">:</span><span class="token punctuation">]</span><span class="token punctuation">,</span> expression<span class="token punctuation">)</span>
    <span class="token comment"># 检验</span>
    <span class="token keyword">if</span> right_crc <span class="token operator">==</span> crc<span class="token punctuation">:</span>  <span class="token comment"># 当尾部的CRC校验码，与首部数据生成的CRC校验码一致时</span>
        word <span class="token operator">=</span><span class="token string">"数据传输过程正常..\n检测出的校验码："</span><span class="token operator">+</span><span class="token builtin">str</span><span class="token punctuation">(</span>crc<span class="token punctuation">)</span><span class="token operator">+</span><span class="token string">'\n数据尾部校验码：'</span><span class="token operator">+</span><span class="token builtin">str</span><span class="token punctuation">(</span>right_crc<span class="token punctuation">)</span>
    <span class="token keyword">else</span><span class="token punctuation">:</span>
        word <span class="token operator">=</span><span class="token string">"数据传输过程出错..\n检测出的校验码："</span><span class="token operator">+</span><span class="token builtin">str</span><span class="token punctuation">(</span>crc<span class="token punctuation">)</span><span class="token operator">+</span><span class="token string">'\n数据尾部校验码：'</span><span class="token operator">+</span><span class="token builtin">str</span><span class="token punctuation">(</span>right_crc<span class="token punctuation">)</span>

    <span class="token keyword">for</span> sock <span class="token keyword">in</span> SocketList<span class="token punctuation">:</span>
        <span class="token comment"># sock.send((str(addr)+': '+content).encode('utf-8'))</span>
        sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'Teacher: '</span> <span class="token operator">+</span> word<span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">#接收一个客户端连接，及其发送来数据</span>
<span class="token keyword">def</span> <span class="token function">read_client</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span>nickname<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">try</span><span class="token punctuation">:</span>
        <span class="token comment">#接受客户端发送来的数据</span>
        <span class="token keyword">return</span> s<span class="token punctuation">.</span>recv<span class="token punctuation">(</span><span class="token number">2048</span><span class="token punctuation">)</span><span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span>
    <span class="token keyword">except</span><span class="token punctuation">:</span>
        <span class="token comment">#客户端异常，连接失败，则删除该socket</span>
        <span class="token comment"># print(str(addr)+'已下线！')</span>
        <span class="token keyword">print</span><span class="token punctuation">(</span>nickname <span class="token operator">+</span> <span class="token string">'已下线！'</span><span class="token punctuation">)</span>
        SocketList<span class="token punctuation">.</span>remove<span class="token punctuation">(</span>s<span class="token punctuation">)</span>
        Nickname<span class="token punctuation">.</span>remove<span class="token punctuation">(</span>nickname<span class="token punctuation">)</span>
        <span class="token keyword">for</span> sock <span class="token keyword">in</span> SocketList<span class="token punctuation">:</span>
            sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'系统消息：'</span> <span class="token operator">+</span> nickname <span class="token operator">+</span> <span class="token string">'已下线！'</span><span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">#多线程：将收到的消息发送给所有客户端</span>
<span class="token keyword">def</span> <span class="token function">send_client</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span>nickname<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">try</span><span class="token punctuation">:</span>
        <span class="token comment"># s.send((','.join(Nickname)).encode('utf-8')) #将用户列表发送给各客户端</span>
        <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
            content <span class="token operator">=</span> read_client<span class="token punctuation">(</span>s<span class="token punctuation">,</span>nickname<span class="token punctuation">)</span> <span class="token comment">#客户端消息</span>
            <span class="token keyword">if</span> content <span class="token keyword">is</span> <span class="token boolean">None</span><span class="token punctuation">:</span> <span class="token comment">#如果没有结束循环</span>
                <span class="token keyword">break</span>
            <span class="token keyword">else</span><span class="token punctuation">:</span> <span class="token comment">#如果有将消息保存到历史记录</span>
                <span class="token comment"># TextList.append(str(addr)+': '+content)</span>
                TextList<span class="token punctuation">.</span>append<span class="token punctuation">(</span>nickname <span class="token operator">+</span> <span class="token string">': '</span> <span class="token operator">+</span> content<span class="token punctuation">)</span>
            <span class="token comment">#将一个客户端发送过来的数据广播给其他客户端</span>
            <span class="token keyword">for</span> sock <span class="token keyword">in</span> SocketList<span class="token punctuation">:</span>
                <span class="token comment"># sock.send((str(addr)+': '+content).encode('utf-8'))</span>
                sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span>nickname <span class="token operator">+</span> <span class="token string">': '</span> <span class="token operator">+</span> content<span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

            CheckCRC<span class="token punctuation">(</span>content<span class="token punctuation">)</span>

    <span class="token keyword">except</span> Exception <span class="token keyword">as</span> e<span class="token punctuation">:</span>
        <span class="token comment"># print(repr())</span>
        <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'广播未成功！'</span><span class="token punctuation">)</span>

QianYan <span class="token operator">=</span> <span class="token punctuation">[</span>
    <span class="token string">'你好呀！今天我们一起来学习SW。'</span><span class="token punctuation">,</span>
           <span class="token string">'可靠传输机制是为了使数据可以正确稳定的传输和接收而制定的规则。'</span><span class="token punctuation">,</span>
           <span class="token string">'流量控制是数据链路层的一种功能，流量控制对数据链路上的帧的发送速率进行控制，以使接收方有足够的缓冲空间来接受每个帧。'</span><span class="token punctuation">,</span>
           <span class="token string">'流量控制的基本方法是由接收方控制发送方发送数据的速率。'</span><span class="token punctuation">,</span>
           <span class="token string">'常见的流量控制方式有两种：`停止-等待协议、滑动窗口协议'</span><span class="token punctuation">,</span>
           <span class="token string">'那么，让我们开始体验停止-等待协议SW的魅力吧！'</span><span class="token punctuation">,</span>
           <span class="token string">'\n\n请输入高于4位的二进制数据'</span><span class="token punctuation">]</span>

<span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
    client<span class="token punctuation">,</span>addr <span class="token operator">=</span> server<span class="token punctuation">.</span>accept<span class="token punctuation">(</span><span class="token punctuation">)</span>
    SocketList<span class="token punctuation">.</span>append<span class="token punctuation">(</span>client<span class="token punctuation">)</span>

    nickname <span class="token operator">=</span> client<span class="token punctuation">.</span>recv<span class="token punctuation">(</span><span class="token number">2048</span><span class="token punctuation">)</span><span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span>
    <span class="token comment"># print(str(addr)+'已加入！')</span>

    <span class="token keyword">if</span> nickname <span class="token keyword">in</span> Nickname<span class="token punctuation">:</span>
        i <span class="token operator">=</span> <span class="token number">1</span>
        <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
            <span class="token keyword">if</span> nickname<span class="token operator">+</span><span class="token builtin">str</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span> <span class="token keyword">in</span> Nickname<span class="token punctuation">:</span>
                i <span class="token operator">=</span> i<span class="token operator">+</span><span class="token number">1</span>
            <span class="token keyword">else</span><span class="token punctuation">:</span>
                nickname <span class="token operator">=</span> nickname <span class="token operator">+</span> <span class="token builtin">str</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span>
                <span class="token keyword">break</span>
    Nickname<span class="token punctuation">.</span>append<span class="token punctuation">(</span>nickname<span class="token punctuation">)</span>
    <span class="token keyword">print</span><span class="token punctuation">(</span>nickname <span class="token operator">+</span> <span class="token string">'已加入！'</span><span class="token punctuation">)</span>

    <span class="token keyword">for</span> sock <span class="token keyword">in</span> SocketList<span class="token punctuation">:</span>
        <span class="token keyword">for</span> i <span class="token keyword">in</span> QianYan<span class="token punctuation">:</span>
            sock<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token string">'Teacher: '</span> <span class="token operator">+</span> i<span class="token punctuation">)</span><span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
            time<span class="token punctuation">.</span>sleep<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span>

    cnt <span class="token operator">=</span> cnt <span class="token operator">+</span> <span class="token number">1</span>

    <span class="token comment">#每当有客户连接后，就启动一个线程为其服务</span>
    <span class="token comment">#加入线程中跑，加入函数为send_client，参数为client,nickname</span>
    threading<span class="token punctuation">.</span>Thread<span class="token punctuation">(</span>target<span class="token operator">=</span>send_client<span class="token punctuation">,</span> args<span class="token operator">=</span><span class="token punctuation">(</span>client<span class="token punctuation">,</span>nickname<span class="token punctuation">,</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>start<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<pre class="line-numbers language-py" data-language="py"><code class="language-py"><span class="token comment">#客户端</span>
<span class="token keyword">import</span> socket
<span class="token keyword">import</span> threading
<span class="token keyword">from</span> tkinter <span class="token keyword">import</span> <span class="token operator">*</span>
<span class="token keyword">import</span> tkinter<span class="token punctuation">.</span>messagebox <span class="token comment">#弹窗库</span>
<span class="token keyword">from</span> tkinter <span class="token keyword">import</span> scrolledtext  <span class="token comment">#滚动文本框</span>

server_host <span class="token operator">=</span> socket<span class="token punctuation">.</span>gethostname<span class="token punctuation">(</span><span class="token punctuation">)</span>
server_port <span class="token operator">=</span> <span class="token number">9999</span>

client <span class="token operator">=</span> socket<span class="token punctuation">.</span>socket<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#创建socket对象</span>
<span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'Connecting......'</span><span class="token punctuation">)</span>


<span class="token comment">#登入窗口：输入呢称</span>
<span class="token keyword">def</span> <span class="token function">LoginWindow</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    root <span class="token operator">=</span> Tk<span class="token punctuation">(</span><span class="token punctuation">)</span>
    root<span class="token punctuation">.</span>title<span class="token punctuation">(</span><span class="token string">'一起来聊天 · 登录'</span><span class="token punctuation">)</span> <span class="token comment">#窗口标题</span>
    root<span class="token punctuation">.</span>geometry<span class="token punctuation">(</span><span class="token string">'300x150'</span><span class="token punctuation">)</span> <span class="token comment">#窗口大小</span>
    root<span class="token punctuation">.</span>geometry<span class="token punctuation">(</span><span class="token string">'+500+300'</span><span class="token punctuation">)</span> <span class="token comment">#改变窗体位置（‘+横坐标+纵坐标’）</span>
    nickname <span class="token operator">=</span> StringVar<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#昵称变量（对象）:在使用界面编程的时候，有些时候是需要跟踪变量的值的变化，以保证值的变更随时可以显示在界面上</span>
    root<span class="token punctuation">.</span>resizable<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token comment">#将窗口大小设置为不可变</span>

    <span class="token comment">#登录函数（检查用户名是否为空，以及长度）</span>
    <span class="token keyword">def</span> <span class="token function">Login_in</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
        name <span class="token operator">=</span> nickname<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#????</span>
        <span class="token keyword">if</span> <span class="token keyword">not</span> name<span class="token punctuation">:</span>
            tkinter<span class="token punctuation">.</span>messagebox<span class="token punctuation">.</span>showwarning<span class="token punctuation">(</span><span class="token string">'Warning'</span><span class="token punctuation">,</span> message<span class="token operator">=</span><span class="token string">'用户名为空！'</span><span class="token punctuation">)</span> <span class="token comment">#消息警告框</span>
        <span class="token keyword">elif</span> <span class="token builtin">len</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span> <span class="token operator">></span> <span class="token number">10</span><span class="token punctuation">:</span>
            tkinter<span class="token punctuation">.</span>messagebox<span class="token punctuation">.</span>showwarning<span class="token punctuation">(</span><span class="token string">'Warning'</span><span class="token punctuation">,</span> message<span class="token operator">=</span><span class="token string">'用户名过长！最多为十个字符！'</span><span class="token punctuation">)</span>
        <span class="token keyword">else</span><span class="token punctuation">:</span>
            root<span class="token punctuation">.</span>destroy<span class="token punctuation">(</span><span class="token punctuation">)</span>
            client<span class="token punctuation">.</span>connect<span class="token punctuation">(</span><span class="token punctuation">(</span>server_host<span class="token punctuation">,</span> server_port<span class="token punctuation">)</span><span class="token punctuation">)</span>  <span class="token comment"># 连接服务端，指定主机和端口</span>
            <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'Connecting is successful!'</span><span class="token punctuation">)</span>
            client<span class="token punctuation">.</span>send<span class="token punctuation">(</span>name<span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>  <span class="token comment"># 传递用户昵称</span>
            ChatRoom<span class="token punctuation">(</span>name<span class="token punctuation">)</span>  <span class="token comment"># 打开聊天窗口</span>

    <span class="token comment">#登录按钮、输入提示标签、输入框</span>
    Button<span class="token punctuation">(</span>root<span class="token punctuation">,</span> text<span class="token operator">=</span><span class="token string">"登录"</span><span class="token punctuation">,</span> command<span class="token operator">=</span>Login_in<span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">8</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">90</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">35</span><span class="token punctuation">)</span>
    Label<span class="token punctuation">(</span>root<span class="token punctuation">,</span> text<span class="token operator">=</span><span class="token string">'请输入昵称'</span><span class="token punctuation">,</span> font<span class="token operator">=</span><span class="token punctuation">(</span><span class="token string">'Fangsong'</span><span class="token punctuation">,</span> <span class="token number">12</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">10</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">20</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">50</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">80</span><span class="token punctuation">)</span>
    Entry<span class="token punctuation">(</span>root<span class="token punctuation">,</span> textvariable<span class="token operator">=</span>nickname<span class="token punctuation">,</span> font<span class="token operator">=</span><span class="token punctuation">(</span><span class="token string">'Fangsong'</span><span class="token punctuation">,</span> <span class="token number">11</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">30</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">30</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">180</span><span class="token punctuation">)</span>

    root<span class="token punctuation">.</span>mainloop<span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">#聊天窗口</span>
<span class="token keyword">def</span> <span class="token function">ChatRoom</span><span class="token punctuation">(</span>nickname<span class="token punctuation">)</span><span class="token punctuation">:</span>
    root <span class="token operator">=</span> Tk<span class="token punctuation">(</span><span class="token punctuation">)</span>
    root<span class="token punctuation">.</span>geometry<span class="token punctuation">(</span><span class="token string">'650x400'</span><span class="token punctuation">)</span>  <span class="token comment"># 窗口大小</span>
    root<span class="token punctuation">.</span>resizable<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>  <span class="token comment"># 将窗口大小设置为不可变</span>
    root<span class="token punctuation">.</span>geometry<span class="token punctuation">(</span><span class="token string">'+500+300'</span><span class="token punctuation">)</span>  <span class="token comment"># 改变窗体位置（‘+横坐标+纵坐标’）</span>

    <span class="token comment"># content = client.recv(2048).decode('utf-8')</span>
    <span class="token comment"># if content != 'No message.':</span>
    <span class="token comment">#     past_text = content + '\n------以上是历史消息------\n'</span>

    <span class="token comment"># 从服务器端获取当前用户列表</span>
    <span class="token comment"># UserList = []</span>
    <span class="token comment"># UserList = client.recv(2048).decode('utf-8').split(',')</span>
    <span class="token comment"># UserList.insert(0, '------当前用户列表------')</span>

    <span class="token comment"># 窗口标题</span>
    <span class="token comment"># nickname = UserList[len(UserList)-1]</span>
    root<span class="token punctuation">.</span>title<span class="token punctuation">(</span><span class="token string">'一起来聊天 · '</span> <span class="token operator">+</span> nickname<span class="token punctuation">)</span>

    <span class="token comment"># name_text = StringVar()</span>
    <span class="token comment"># name_text.set(UserList)  # 用户列表文本设置</span>
    <span class="token comment"># listbox1 = Listbox(root, listvariable=name_text)  # 用户列表，使用Listbox组件</span>
    <span class="token comment"># listbox1.place(x=5, y=0, width=500, height=400)</span>

    img_png <span class="token operator">=</span> PhotoImage<span class="token punctuation">(</span><span class="token builtin">file</span><span class="token operator">=</span><span class="token string">'QQ图片20220901201640.png'</span><span class="token punctuation">)</span>
    label_img <span class="token operator">=</span> Label<span class="token punctuation">(</span>root<span class="token punctuation">,</span> image<span class="token operator">=</span>img_png<span class="token punctuation">)</span>
    label_img<span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">400</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">350</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">300</span><span class="token punctuation">)</span>

    <span class="token comment">#聊天界面</span>
    <span class="token comment"># content = client.recv(2048).decode('utf-8')</span>
    ChatBox <span class="token operator">=</span> scrolledtext<span class="token punctuation">.</span>ScrolledText<span class="token punctuation">(</span>root<span class="token punctuation">)</span>  <span class="token comment"># 聊天信息窗口，使用ScrolledText组件制作</span>
    ChatBox<span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">5</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">470</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">300</span><span class="token punctuation">)</span>
    <span class="token comment"># ChatBox.pack()</span>
    <span class="token comment"># ChatBox.insert('end',content)</span>

    <span class="token keyword">def</span> <span class="token function">read_server</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
            content <span class="token operator">=</span> c<span class="token punctuation">.</span>recv<span class="token punctuation">(</span><span class="token number">2048</span><span class="token punctuation">)</span><span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span>
            ChatBox<span class="token punctuation">.</span>insert<span class="token punctuation">(</span><span class="token string">'end'</span><span class="token punctuation">,</span> <span class="token string">'\n'</span><span class="token operator">+</span>content<span class="token operator">+</span><span class="token string">'\n'</span><span class="token punctuation">)</span>
            ChatBox<span class="token punctuation">.</span>see<span class="token punctuation">(</span>tkinter<span class="token punctuation">.</span>END<span class="token punctuation">)</span>  <span class="token comment"># ScrolledText组件方法，自动定位到结尾，否则只有消息在涨，窗口拖动条不动</span>
            ChatBox<span class="token punctuation">.</span>update<span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token comment"># 更新聊天信息窗口，显示新的信息</span>
    threading<span class="token punctuation">.</span>Thread<span class="token punctuation">(</span>target<span class="token operator">=</span>read_server<span class="token punctuation">,</span> args<span class="token operator">=</span><span class="token punctuation">(</span>client<span class="token punctuation">,</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>start<span class="token punctuation">(</span><span class="token punctuation">)</span>

    <span class="token comment">#聊天输入框</span>
    word <span class="token operator">=</span> StringVar<span class="token punctuation">(</span><span class="token punctuation">)</span>
    word<span class="token punctuation">.</span><span class="token builtin">set</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span>
    SentBox <span class="token operator">=</span> Entry<span class="token punctuation">(</span>root<span class="token punctuation">,</span>width<span class="token operator">=</span><span class="token number">140</span><span class="token punctuation">,</span>textvariable<span class="token operator">=</span>word<span class="token punctuation">)</span> <span class="token comment">#建一个输入框</span>
    SentBox<span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">5</span><span class="token punctuation">,</span>y<span class="token operator">=</span><span class="token number">305</span><span class="token punctuation">,</span>width<span class="token operator">=</span><span class="token number">475</span><span class="token punctuation">,</span>height<span class="token operator">=</span><span class="token number">90</span><span class="token punctuation">)</span> <span class="token comment">#设置大小和位置</span>

    <span class="token comment">#发送按钮</span>
    <span class="token keyword">def</span> <span class="token function">sendtext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
        content <span class="token operator">=</span> word<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">#获得文本内容</span>
        <span class="token keyword">if</span> content<span class="token operator">==</span><span class="token string">'end'</span><span class="token punctuation">:</span>
            client<span class="token punctuation">.</span>close<span class="token punctuation">(</span><span class="token punctuation">)</span>
        client<span class="token punctuation">.</span>send<span class="token punctuation">(</span>content<span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        word<span class="token punctuation">.</span><span class="token builtin">set</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span> <span class="token comment">#用了一个标记记录点击的状态，不管内容是什么点了就变</span>

    sendButton <span class="token operator">=</span> Button<span class="token punctuation">(</span>root<span class="token punctuation">,</span> text<span class="token operator">=</span><span class="token string">'发 送'</span><span class="token punctuation">,</span> font<span class="token operator">=</span><span class="token punctuation">(</span><span class="token string">'Fangsong'</span><span class="token punctuation">,</span> <span class="token number">18</span><span class="token punctuation">)</span><span class="token punctuation">,</span> bg<span class="token operator">=</span><span class="token string">'white'</span><span class="token punctuation">,</span> command<span class="token operator">=</span>sendtext<span class="token punctuation">)</span>
    sendButton<span class="token punctuation">.</span>place<span class="token punctuation">(</span>x<span class="token operator">=</span><span class="token number">490</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">308</span><span class="token punctuation">,</span> width<span class="token operator">=</span><span class="token number">150</span><span class="token punctuation">,</span> height<span class="token operator">=</span><span class="token number">85</span><span class="token punctuation">)</span>

    root<span class="token punctuation">.</span>mainloop<span class="token punctuation">(</span><span class="token punctuation">)</span>

LoginWindow<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h1 id="实训二阶段"><a href="#实训二阶段" class="headerlink" title="实训二阶段"></a>实训二阶段</h1><blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/Protinx/article/details/124586695">(29条消息) Cisco Packet Tracer安装详解_@Protinx的博客-CSDN博客_cisco packet tracer</a></p>
<p> <a target="_blank" rel="noopener" href="https://so.csdn.net/so/search?q=%E6%80%9D%E7%A7%91%E6%A8%A1%E6%8B%9F%E5%99%A8&spm=1001.2101.3001.7020">思科模拟器</a>Cisco Packet <a target="_blank" rel="noopener" href="https://so.csdn.net/so/search?q=Tracer&spm=1001.2101.3001.7020">Tracer</a>是一个功能强大的网络仿真程序，允许学生实验与网络行为。但是这个软件是纯软件模拟，和真实的环境有差距，命令也不全。适合新手教程教学使用。</p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_41625827/article/details/106115226">(29条消息) 思科Packet Tracer基础使用教程_冰镇阔落的博客-CSDN博客_cisco packet tracer教程</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_43598138/article/details/104317148">(29条消息) Cisco Packet Tracer软件介绍与使用方法_发光吖的博客-CSDN博客_packet tracer</a></p>
<ul>
<li><p>一般选择高型号的路由器（可支持的命令比较多），在Packet Tracer 5.3里面推荐选择2811系列路由器。</p>
</li>
<li><p>交换机也选择高型号的，推荐选择2960系列。（注：2xxx系列为二层交换机，3xxx系列为三层交换机。两者交换功能相同，但三层交换机多了路由功能，在一些情况下三层交换机可以代替路由器，但不能完全替代路由器）</p>
<p>交换机（Switch）意为“<a target="_blank" rel="noopener" href="https://baike.baidu.com/item/%E5%BC%80%E5%85%B3/2275072?fromModule=lemma_inlink">开关</a>”是一种用于电（光）信号转发的<a target="_blank" rel="noopener" href="https://baike.baidu.com/item/%E7%BD%91%E7%BB%9C%E8%AE%BE%E5%A4%87/7667828?fromModule=lemma_inlink">网络设备</a>。它可以为接入交换机的任意两个<a target="_blank" rel="noopener" href="https://baike.baidu.com/item/%E7%BD%91%E7%BB%9C%E8%8A%82%E7%82%B9/9338583?fromModule=lemma_inlink">网络节点</a>提供独享的电信号通路。</p>
</li>
<li><p>一般情况下选择（自动线）即可，或选择（直通线）。若方案要求选择专线，则需要选择（专线）。方案中线路大多为直通线（即以太网线），少数会有专线要求。<br> 点击一下所要使用的线，然后点击需要连线的设备接口，从一个设备接口连线至另一个设备接口。（注：自动线不需要选择接口，其他两种线需要手动选择接口。直通线选择Fast开头的接口，专线选择Serial开头的接口）<br>注：自动线连好为虚线；直通线连好为实线。</p>
</li>
</ul>
<p>交换机是用来连接局域网的，路由器是用来连接互联网的（也可以连接多个局域网）</p>
</blockquote>
<img src="https://zhang2002gz.oss-cn-qingdao.aliyuncs.com/img/image-20220902192351180.png" alt="image-20220902192351180" style="zoom: 50%;" />

<p>各线缆两端有不同颜色的圆点，它们分别表示什么样的含义呢？</p>
<table>
<thead>
<tr>
<th>链路圆点的状态</th>
<th>含义</th>
</tr>
</thead>
<tbody><tr>
<td>亮绿色</td>
<td>物理连接准备就绪，还没有Line Protocol status 的指示</td>
</tr>
<tr>
<td>闪烁的绿色</td>
<td>连接激活</td>
</tr>
<tr>
<td>红色</td>
<td>物理连接不通，没有信号</td>
</tr>
<tr>
<td>黄色</td>
<td>交换机端口处于”阻塞”状态</td>
</tr>
</tbody></table>
<blockquote>
<p>路由器和交换机区别</p>
<ul>
<li>路由器：寻址，转发（依靠 IP 地址），交换机：过滤，转发（依靠 MAC 地址）</li>
<li>交换机用于连接局域网，数据包在局域网内网的数据转发，路由器用于连接局域网和外网，数据包可以在不同局域网转发。</li>
<li>交换机工作于TCP/IP协议的最后一层数据链路层（物理层），路由器工作于网络层</li>
<li>交换机负责具体的数据包传输，路由器不负责包的实际传输，路由器只封装好要传输的数据包，然后交给交换机去传输（不一定是交换机，可能是其他传输技术），用java比喻大概简单理解为路由器是抽象类，定义好传输的数据包格式，交换机是具体实现类，也可以有其他实现类</li>
<li>交换机没有MAC地址和IP地址，路由器有MAC地址和IP地址（指纯碎的交换机和路由器，三层交换机是可以有IP地址的，路由器也有内置交换机功能的）<br>原文链接：<a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_21187515/article/details/119416934">https://blog.csdn.net/qq_21187515/article/details/119416934</a></li>
</ul>
</blockquote>
<pre class="line-numbers language-python" data-language="python"><code class="language-python">Router<span class="token operator">></span>enable 
Router<span class="token comment">#</span>
<span class="token punctuation">(</span>Router<span class="token operator">></span>en<span class="token punctuation">)</span>
在用户模式下输入enable即可进入特权模式。第二级别模式，可以对设备进行所有的查看、测试及简单的配置。

Router<span class="token comment">#configure terminal </span>
Enter configuration commands<span class="token punctuation">,</span> one per line<span class="token punctuation">.</span>  End <span class="token keyword">with</span> CNTL<span class="token operator">/</span>Z<span class="token punctuation">.</span>
Router<span class="token punctuation">(</span>config<span class="token punctuation">)</span><span class="token comment">#</span>
<span class="token punctuation">(</span>Router<span class="token comment">#conf t)</span>
在特权模式下，输入configure terminal即可进入配置模式。第三级别模式，可以对设备进行管理配置。

Router<span class="token punctuation">(</span>config<span class="token punctuation">)</span><span class="token comment">#interface fastEthernet 0/0</span>
Router<span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span><span class="token comment">#</span>
<span class="token punctuation">(</span>Router<span class="token punctuation">(</span>config<span class="token punctuation">)</span><span class="token comment">#int fa0/0  //定义0/0接口)</span>
其他配置模式Router<span class="token punctuation">(</span>config<span class="token operator">-</span>???<span class="token punctuation">)</span><span class="token comment">#。第四级别模式，可以对设备进行各种专用配置。如，进入配置设备接口的模式</span>

Router<span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span><span class="token comment">#ip address 192.168.1.2 255.255.255.0</span>
<span class="token punctuation">(</span>Router<span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span><span class="token comment">#ip add 192.168.1.254 255.255.255.0)</span>
配置ip地址

R2<span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span><span class="token comment">#no shutdown</span>
<span class="token punctuation">(</span>Router<span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span><span class="token comment">#no sh)</span>
激活接口

<span class="token punctuation">(</span>Router<span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span><span class="token comment">#do wr)</span>
Building configuration<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
Router<span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span><span class="token comment">#do show ip rou               //显示所有IP路由</span>

C    <span class="token number">192.168</span><span class="token number">.1</span><span class="token number">.0</span><span class="token operator">/</span><span class="token number">24</span> <span class="token keyword">is</span> directly connected<span class="token punctuation">,</span> FastEthernet0<span class="token operator">/</span><span class="token number">0</span>		<span class="token operator">//</span>路由表

<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<pre class="line-numbers language-python" data-language="python"><code class="language-python">路由器配置
Router<span class="token operator">></span>en
Router<span class="token comment">#</span>
Router<span class="token comment">#conf t</span>
Router<span class="token punctuation">(</span>config<span class="token punctuation">)</span><span class="token comment">#int fa0/0                       //定义0/0接口</span>
Router<span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span><span class="token comment">#ip add 192.168.1.254 255.255.255.0</span>
Router<span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span><span class="token comment">#no sh </span>
Router<span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span><span class="token comment">#int fa0/1                    //定义0/1接口</span>
Router<span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span><span class="token comment">#ip add 192.168.2.254 255.255.255.0</span>
Router<span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span><span class="token comment">#no sh                        //激活接口</span>
Router<span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span><span class="token comment">#do wr</span>
Router<span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span><span class="token comment">#do show ip rou               //显示所有IP路由</span>
Codes<span class="token punctuation">:</span> C <span class="token operator">-</span> connected<span class="token punctuation">,</span> S <span class="token operator">-</span> static<span class="token punctuation">,</span> I <span class="token operator">-</span> IGRP<span class="token punctuation">,</span> R <span class="token operator">-</span> RIP<span class="token punctuation">,</span> M <span class="token operator">-</span> mobile<span class="token punctuation">,</span> B <span class="token operator">-</span> BGP
       D <span class="token operator">-</span> EIGRP<span class="token punctuation">,</span> EX <span class="token operator">-</span> EIGRP external<span class="token punctuation">,</span> O <span class="token operator">-</span> OSPF<span class="token punctuation">,</span> IA <span class="token operator">-</span> OSPF inter area
       N1 <span class="token operator">-</span> OSPF NSSA external <span class="token builtin">type</span> <span class="token number">1</span><span class="token punctuation">,</span> N2 <span class="token operator">-</span> OSPF NSSA external <span class="token builtin">type</span> <span class="token number">2</span>
       E1 <span class="token operator">-</span> OSPF external <span class="token builtin">type</span> <span class="token number">1</span><span class="token punctuation">,</span> E2 <span class="token operator">-</span> OSPF external <span class="token builtin">type</span> <span class="token number">2</span><span class="token punctuation">,</span> E <span class="token operator">-</span> EGP
       i <span class="token operator">-</span> IS<span class="token operator">-</span>IS<span class="token punctuation">,</span> L1 <span class="token operator">-</span> IS<span class="token operator">-</span>IS level<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> L2 <span class="token operator">-</span> IS<span class="token operator">-</span>IS level<span class="token operator">-</span><span class="token number">2</span><span class="token punctuation">,</span> ia <span class="token operator">-</span> IS<span class="token operator">-</span>IS inter area
       <span class="token operator">*</span> <span class="token operator">-</span> candidate default<span class="token punctuation">,</span> U <span class="token operator">-</span> per<span class="token operator">-</span>user static route<span class="token punctuation">,</span> o <span class="token operator">-</span> ODR
       P <span class="token operator">-</span> periodic downloaded static route
 
Gateway of last resort <span class="token keyword">is</span> <span class="token keyword">not</span> <span class="token builtin">set</span>
 
C    <span class="token number">192.168</span><span class="token number">.1</span><span class="token number">.0</span><span class="token operator">/</span><span class="token number">24</span> <span class="token keyword">is</span> directly connected<span class="token punctuation">,</span> FastEthernet0<span class="token operator">/</span><span class="token number">0</span>      <span class="token operator">//</span>路由表
C    <span class="token number">192.168</span><span class="token number">.2</span><span class="token number">.0</span><span class="token operator">/</span><span class="token number">24</span> <span class="token keyword">is</span> directly connected<span class="token punctuation">,</span> FastEthernet0<span class="token operator">/</span><span class="token number">1</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_39524009/article/details/81073693">(29条消息) 交换机实验、VLAN创建_Air_Echo的博客-CSDN博客_创建vlan</a></p>
</blockquote>
<blockquote>
<p>打开<strong>【PC中 &gt;&gt; Desktop &gt;&gt; Commond prompt】</strong></p>
<p>pc0上 ping 192.168.20.1 (PC1)的ip地址</p>
</blockquote>
<blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/VariatioZbw/article/details/108212741">(29条消息) Cisco Packet Tracer 命令大全 【思科交换机模拟器命令大全】_zhangbw~的博客-CSDN博客_cisco packet tracer命令行</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_40163937/article/details/88818072">(29条消息) Cisco Packet Tracer—VLAN配置详解_HOPEAMOR的博客-CSDN博客</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_34194317/article/details/92553357">(29条消息) cisco交换机 配置一组端口,interface range_weixin_34194317的博客-CSDN博客</a></p>
</blockquote>
<blockquote>
<p>当使用<strong>interface range</strong>命令时有如下的规则:</p>
<p>有效的组范围:<br>vlan从1 到4094<br>fastethernet 槽位/{first port} - {last port}, 槽位为0<br>gigabitethernet槽位/{first port} - {last port},槽位为0<br>port-channel port-channel-number - port-channel-number, port-channel号从1到64<br>端口号之间需要加入空格，如：interface range fastethernet 0/1 – 5 是有效的，而interface range fastethernet 0/1-5 是无效的.<br>interface range 命令只能配置已经存在的interface vlan<br>所有在同一组的端口必须是相同类别的。<br>见以下例子:</p>
<p>Switch# configure terminal<br>Switch(config)# interface range fastethernet0/1 - 5 </p>
</blockquote>
<blockquote>
<p><strong>#switch trunk encapsulation dot1q</strong></p>
<p> <strong>IEEE 802.1Q协议</strong>，是vlan的一种封装方式，是公有协议。 还有一种trunk协议，是ISL，也是vlan的一种封装方式，不过这是Cisco思科私有协议，其他厂商不能用。</p>
<p><strong>#switchport trunk</strong>是配置允许通过的vlan；<br>　　switchport mode trunk是将端口配置成trunk模式；<br>　　mode trunk //端口模式为trunk<br>　　switchport trunk encapsulation dot1q //trunk协议封装为dot1q<br>　　dot1q就是 IEEE 802.1Q协议，是vlan的一种封装方式，是公有协议。<br>　　还有一种trunk协议，是ISL，也是vlan的一种封装方式，不过这是Cisco思科私有协议，其他厂商不能用。</p>
</blockquote>
<h2 id="实训1：局域网分层结构"><a href="#实训1：局域网分层结构" class="headerlink" title="实训1：局域网分层结构"></a>实训1：局域网分层结构</h2><pre class="line-numbers language-none"><code class="language-none">1.基本任务
三层交换上实现VLAN间路由；
两层交换机上划分VLAN；
VLAN数目不少于2个；
自行规划IP地址<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<blockquote>
<p>技术原理</p>
<ul>
<li>三层交换机具备网络层的功能，实现 VLAN 相互访问的原理是：利用三层交换机的路由功能，通过识别数据包的 IP 地址，查找路由表进行选路转发，三层交换机利用直连路由可以实现不同 VLAN 之间的相互访问。</li>
<li>三层交换机给接口配置 IP 地址。采用 SVI（交换虚拟接口）的方式实现 VLAN 间互连。<strong>SVI 是指为交换机中的VLAN 创建虚拟接口，并且配置 IP 地址</strong>。</li>
<li>Tag VLAN是基于交换机端口的一种类型，主要用于<strong>使交换机的相同Vlan内的主机之间</strong>可以直接访问，同时对于不同Vlan的主机进行隔离。</li>
<li>trunk主要用在<strong>连接其它交换机</strong>，以便在线路上承载多个vlanWLAN是Wireless Local Area Network的简称，指应用无线通信技术将计算机设备互联起来，构成可以互相通信和实现资源共享的网络体系。</li>
<li>802.1x协议是WLAN第二代的认证技术，它是基于客户端-服务器（Client-Server)结构的访问控制和认证协议。它可以限制未经授权的用户/设备通过接入端口（Access Port)访问LAN/WLAN。</li>
<li>DOT1Q是提供VLAN识别和服务质量(QoS)级别的IEEE标准。电气和电子工程师协会（IEEE，全称是Institute of Electrical and Electronics Engineers）是一个美国的电子技术与信息科学工程师的协会，是世界上最大的非营利性专业技术学会。</li>
<li>ip routing 启用IP路由功能no ip routing 关闭IP路由功能</li>
</ul>
</blockquote>
<blockquote>
<p><strong>二层交换机与三层交换机区别</strong></p>
<p>我们习惯说，<strong>在二层网络环境中相同vlan之间可以通信，不同vlan之间不可以通信，如果想通信必须借助三层设备</strong>，所以说<strong>三层交换机必须要做的事情是路由转发</strong>，但是二、三层交换机具体有什么区别呢？</p>
<ul>
<li><p>二层交换机工作于OSI模型的第2层(数据链路层)，故而称为二层交换机。二层交换技术发展比较成熟，二层交换机属数据链路层设备，可以<strong>识别数据包中的MAC地址信息，根据MAC地址进行转发</strong>，并将这些MAC地址与对应的端口记录在自己内部的一个地址表中。具体的工作流程如下：</p>
<p>（1） 当交换机从某个端口收到一个数据包，它先读取包头中的源MAC地址，这样它就知道源MAC地址的机器是连在哪个端口上的；</p>
<p>（2） 再去读取包头中的目的MAC地址，并在地址表中查找相应的端口；</p>
<p>（3） 如表中有与这目的MAC地址对应的端口，把数据包直接复制到这端口上；</p>
<p>（4） 如表中找不到相应的端口则把数据包广播到所有端口上，当目的机器对源机器回应时，交换机又可以学习一目的MAC地址与哪个端口对应，在下次传送数据时就不再需要对所有端口进行广播了。</p>
<p>​    不断的循环这个过程，对于全网的MAC地址信息都可以学习到，二层交换机就是这样建立和维护它自己的地址表。二层交换技术从网桥发展到VLAN（虚拟局域网），在局域网建设和改造中得到了广泛的应用。第二层交换技术是工作在OSI七层网络模型中的第二层，即数据链路层。它按照所接收到数据包的目的MAC地址来进行转发，对于网络层或者高层协议来说是透明的。<strong>它不处理网络层的IP地址</strong>，不处理高层协议的诸如TCP、UDP的端口地址，它只需要数据包的物理地址即MAC地址，<strong>数据交换是靠硬件来实现的，其速度相当快，这是二层交换的一个显著的优点</strong>。但是，它<strong>不能处理不同IP子网之间的数据交换</strong>。</p>
<p>​    传统的路由器可以处理大量的跨越IP子网的数据包，但是它的转发效率比二层低，因此要想利用二层转发效率高这一优点，又要处理三层IP数据包，三层交换技术就诞生了。</p>
</li>
<li><p>三层交换（也称多层交换技术，或IP交换技术）是相对于传统交换概念而提出的。众所周知，传统的交换技术是在OSI网络标准模型中的第二层——数据链路层进行操作的，而三层交换技术是在网络模型中的第三层实现了数据包的高速转发。简单地说，<strong>三层交换技术就是：二层交换技术＋三层转发技术。</strong>三层交换机就是具有部分路由器功能的交换机。三层交换机的最重要目的是加快大型局域网内部的数据交换，所具有的路由功能也是为这目的服务的，能够做到一次路由，多次转发。对于数据包转发等规律性的过程由硬件高速实现，而像路由信息更新、路由表维护、路由计算、路由确定等功能，由软件实现。三层交换技术就是二层交换技术+三层转发技术。三层交换技术的出现，解决了局域网中网段划分之后，网段中子网必须依赖路由器进行管理的局面，解决了传统路由器低速、复杂所造成的网络瓶颈问题。</p>
</li>
</ul>
</blockquote>
<p><img src="https://img2020.cnblogs.com/blog/1280419/202004/1280419-20200425105756156-1041750903.png" alt="img"></p>
<blockquote>
<p>实验步骤</p>
<p>1）在二层交换机上配置 VLAN2、VLAN3，分别将端口 2、端口 3 划分给 VLAN2、VLAN3。<br>（2）<strong>将二层交换机与三层交换机相连的端口 fa 0/1 都定义为 tag Vlan 模式。</strong><br>（3）在三层交换机上配置 VLAN2、VLAN3，此时验证二层交换机 VLAN2、VLAN3下的主机之间不能相互通信。<br>（4）设置三层交换机 VLAN 间的通信，创建 VLAN2,VLAN3 的虚接口，并配置虚接口 VLAN2、VLAN3 的 IP 地址。<br>（5）查看三层交换机路由表。<br>（6）将二层交换机 VLAN2、VLAN3 下的主机默认网关分别设置为相应虚拟接口的 IP 地址。<br>（7）验证二层交换机 VLAN2,VALN3 下的主机之间可以相互通信。</p>
</blockquote>
<blockquote>
<p><strong>switchport access vlan 3</strong><br>语法：<br>switchport access vlan vlan-id<br>no switchport access vlan</p>
<p><strong>该命令把一个Access接口指派给一个VLAN</strong>。使用 no 选项可以把接口指派到缺省的VLAN中。</p>
<p>缺省值：接口缺省的VLAN是 VLAN 1。</p>
<p>命令模式：接口配置模式</p>
<p>适用接口：2层物理接口。</p>
<p>说明：如果指定的VLAN不存在，则系统会创建这个VLAN，并把接口设置为该VLAN的成员。如果指定的VLAN已经存在，则把接口添加到该VLAN中。如果接口是一个Trunk口，该操作没有任何作用。可以用 show vlan 命令查看VLAN信息。</p>
<p>范例：<br>Ruijie(config)# interface f0/1<br>Ruijie(config)# switchport<br>Ruijie(config-if)# switchport access vlan 10<br>本例把 <strong>FastEthernat 0/1 口设置为2层口，并把它加入到 VLAN 10 中。</strong></p>
<p><strong>#switchport mode trunk</strong></p>
<p>语法：</p>
<p>switchport mode { access | trunk }</p>
<p>no switchport mode</p>
<p>该命令<strong>指定一个2层接口的模式，可以把接口指定为 access 接口或者 trunk 接口。</strong>使用 no 选项可以把接口模式恢复为缺省值。</p>
<p>缺省值：接口的缺省模式是 access。</p>
<p>命令模式：接口配置模式</p>
<p>适用接口：2层物理接口、2层Aggregateport接口。</p>
<p>说明：如果一个接口的模式是 access，则该接口只能成为一个VLAN的成员，可以使用 switchport access vlan 命令把它指定给一个VLAN；如果一个接口的模式是 trunk，则该接口可以是多个VLAN的成员，可以用 switchport trunk 命令定义许可VLAN列表决定它所在的VLAN。</p>
<p>范例：</p>
<p>Ruijie(config)# interface f0/1<br>Ruijie(config-if)# switchport mode trunk<br><strong>本例把 FastEthernat 0/1 口设置为 Trunk 接口。</strong></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/ahleung/article/details/100102099">(29条消息) Switchport详细用法_天地良心的博客-CSDN博客</a></p>
</blockquote>
<blockquote>
<p>三个空的的口令分别是：</p>
<ol>
<li>interface e0 //根据图示这个是E0口。</li>
<li>192.168.2.1 255.255.255.0 //R1的S0接口的IP地址和子网掩码。</li>
<li>s0 //这个是送出接口</li>
</ol>
<p><strong>ip routing 是用在三层交换机上打开路由功能，默认是关闭的</strong>，ip router ospf 是在路由器上启用ospf等路由协议，ospf后面还要加个进程号，范围是0-65535，只具有本地意义</p>
<p>ip routing启用IP路由功能：</p>
<ol>
<li><p>配置三层交换机启动路由功能：ip routing 。</p>
</li>
<li><p>配置VLAN IP地址：</p>
<p>interface vlan vlan-id                </p>
<p>Ip address ip-address subnet-mask                </p>
<p>No shutdown</p>
</li>
<li><p>配置接口为三层模式：</p>
<p>no switchport</p>
</li>
<li><p>配置DHCP中继转发：</p>
<p>int vlan vlan-i</p>
<p>Ip helper-address Dhcpserver-address</p>
</li>
<li><p>配置静态路由：</p>
<p>ip route targetnet-address netmask nexthop-address</p>
</li>
<li><p>配置RIP协议：</p>
<p>router rip</p>
</li>
<li><p>查看FIB表：</p>
<p>show ip cef</p>
</li>
<li><p>查看邻接关系表：</p>
<p>show adjacency detail</p>
</li>
<li><p>查看路由表：</p>
<p>show ip route</p>
</li>
</ol>
</blockquote>
<blockquote>
<p>PC1    IP: 192.168.1.2   Submark: 255.255.255.0   Gateway: 192.168.1.1 </p>
<p>PC2    IP: 192.168.2.2   Submark: 255.255.255.0   Gateway: 192.168.2.1 </p>
<p>PC3    IP: 192.168.1.3   Submark: 255.255.255.0   Gateway: 192.168.1.1</p>
<p>二层交换机<br><strong>Switch&gt;en</strong><br><strong>Switch#conf t</strong><br>Enter configuration commands, one per line. End with CNTL/Z.</p>
<p><strong>Switch(config)#vlan 2</strong><br><strong>Switch(config-vlan)#exit</strong><br><strong>Switch(config)#vlan 3</strong></p>
<p><strong>Switch(config-vlan)#int fa 0/2</strong><br><strong>Switch(config-if)#switchport access vlan 2</strong><br>Switch(config-if)#int fa 0/3<br>Switch(config-if)#switchport access vlan 3</p>
<p><strong>Switch(config-if)#int fa 0/1</strong><br><strong>Switch(config-if)#switchport mode trunk</strong></p>
<p>%LINEPROTO-5-UPDOWN: Line protocol on Interface FastEthernet0/1, changed state to down</p>
<p>%LINEPROTO-5-UPDOWN: Line protocol on Interface FastEthernet0/1, changed state to up</p>
<p><strong>Switch(config-if)#end</strong><br>Switch#<br>%SYS-5-CONFIG_I: Configured from console by console</p>
<p><strong>Switch#show vlan</strong></p>
<p>VLAN Name Status Ports</p>
<hr>
<p>1 default active Fa0/4, Fa0/5, Fa0/6, Fa0/7<br>Fa0/8, Fa0/9, Fa0/10, Fa0/11<br>Fa0/12, Fa0/13, Fa0/14, Fa0/15<br>Fa0/16, Fa0/17, Fa0/18, Fa0/19<br>Fa0/20, Fa0/21, Fa0/22, Fa0/23<br>Fa0/24, Gig1/1, Gig1/2<br>2 VLAN0002 active Fa0/2<br>3 VLAN0003 active Fa0/3<br>1002 fddi-default act/unsup<br>1003 token-ring-default act/unsup<br>1004 fddinet-default act/unsup<br>1005 trnet-default act/unsup</p>
<p>VLAN Type SAID MTU Parent RingNo BridgeNo Stp BrdgMode Trans1 Trans2</p>
<hr>
<p>1 enet 100001 1500 - - - - - 0 0<br>2 enet 100002 1500 - - - - - 0 0<br>3 enet 100003 1500 - - - - - 0 0<br>1002 fddi 101002 1500 - - - - - 0 0<br>–More–</p>
</blockquote>
<blockquote>
<p>三层交换机<br><strong>Switch&gt;en</strong><br><strong>Switch#conf t</strong><br>Enter configuration commands, one per line. End with CNTL/Z.</p>
<p><strong>Switch(config)#vlan 2</strong><br><strong>Switch(config-vlan)#exit</strong><br><strong>Switch(config)#vlan 3</strong><br><strong>Switch(config-vlan)#exit</strong></p>
<p><strong>Switch(config)#int fa 0/1</strong><br><strong>Switch(config-if)#switchport trunk encapsulation dot1q</strong><br><strong>Switch(config-if)#switchport mode trunk</strong><br><strong>Switch(config-if)#switchport trunk allowed vlan 2,3</strong><br><strong>Switch(config-if)#exit</strong></p>
<p><strong>Switch(config)#int fa 0/2</strong><br><strong>Switch(config-if)#switchport access vlan 2</strong><br><strong>Switch(config-if)#exit</strong></p>
<p><strong>Switch(config)#int vlan 2</strong></p>
<p>%LINK-5-CHANGED: Interface Vlan2, changed state to up</p>
<p>%LINEPROTO-5-UPDOWN: Line protocol on Interface Vlan2, changed state to up<br><strong>Switch(config-if)#ip address 192.168.1.1 255.255.255.0</strong><br><strong>Switch(config-if)#no shutdown</strong><br><strong>Switch(config-if)#exit</strong><br>Switch(config)#int vlan 3</p>
<p>%LINK-5-CHANGED: Interface Vlan3, changed state to up</p>
<p>%LINEPROTO-5-UPDOWN: Line protocol on Interface Vlan3, changed state to up<br>Switch(config-if)#ip address 192.168.2.1 255.255.255.0<br>Switch(config-if)#no shutdown<br>Switch(config-if)#exit</p>
<p><strong>Switch(config)#ip routing</strong><br><strong>Switch(config)#exit</strong><br>Switch#<br>%SYS-5-CONFIG_I: Configured from console by console</p>
<p><strong>Switch#show ip route</strong><br>Codes: C - connected, S - static, I - IGRP, R - RIP, M - mobile, B - BGP<br>D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area<br>N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2<br>E1 - OSPF external type 1, E2 - OSPF external type 2, E - EGP<br>i - IS-IS, L1 - IS-IS level-1, L2 - IS-IS level-2, ia - IS-IS inter area</p>
<ul>
<li><ul>
<li>candidate default, U - per-user static route, o - ODR<br>P - periodic downloaded static route</li>
</ul>
</li>
</ul>
<p>Gateway of last resort is not set</p>
<p>C 192.168.1.0/24 is directly connected, Vlan2<br>C 192.168.2.0/24 is directly connected, Vlan3</p>
<p><strong>Switch#show vlan</strong></p>
<p>VLAN Name Status Ports</p>
<hr>
<p>1 default active Fa0/3, Fa0/4, Fa0/5, Fa0/6<br>Fa0/7, Fa0/8, Fa0/9, Fa0/10<br>Fa0/11, Fa0/12, Fa0/13, Fa0/14<br>Fa0/15, Fa0/16, Fa0/17, Fa0/18<br>Fa0/19, Fa0/20, Fa0/21, Fa0/22<br>Fa0/23, Fa0/24, Gig0/1, Gig0/2<br>2 VLAN0002 active Fa0/2<br>3 VLAN0003 active<br>1002 fddi-default act/unsup<br>1003 token-ring-default act/unsup<br>1004 fddinet-default act/unsup<br>1005 trnet-default act/unsup</p>
<p>VLAN Type SAID MTU Parent RingNo BridgeNo Stp BrdgMode Trans1 Trans2</p>
<hr>
<p>1 enet 100001 1500 - - - - - 0 0<br>2 enet 100002 1500 - - - - - 0 0<br>3 enet 100003 1500 - - - - - 0 0<br>1002 fddi 101002 1500 - - - - - 0 0<br>–More–</p>
</blockquote>
<blockquote>
<p>PC1 分别 ping PC2 和 PC3</p>
<p> <strong>PC&gt;ipconfig IP</strong></p>
<p>Address………………….: 192.168.1.2 </p>
<p>Subnet Mask…………………: 255.255.255.0 </p>
<p>Default Gateway……………..: 192.168.1.1 </p>
<p><strong>PC&gt;ping 192.168.2.2</strong> </p>
<p>Pinging 192.168.2.2 with 32 bytes of data:</p>
<p> Request timed out. </p>
<p>Reply from 192.168.2.2: bytes=32 time=25ms TTL=127 </p>
<p>Reply from 192.168.2.2: bytes=32 time=20ms TTL=127 </p>
<p>Reply from 192.168.2.2: bytes=32 time=20ms TTL=127 </p>
<p>Ping statistics for 192.168.2.2: </p>
<p>Packets: Sent = 4, Received = 3, Lost = 1 (25% loss), Approximate round trip times in milli-seconds: Minimum = 20ms, Maximum = 25ms, Average = 21ms</p>
</blockquote>
<pre class="line-numbers language-none"><code class="language-none">2.拓展任务
使用VTP管理交换机
启用快速生成树，采用线路冗余的方式增加可靠性。<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre>

<blockquote>
<p><a target="_blank" rel="noopener" href="https://www.cnblogs.com/zoulongbin/p/9047390.html">https://www.cnblogs.com/zoulongbin/p/9047390.html</a></p>
<p>VTP的工作原理</p>
<p>VTP：虚拟局域网中继协议，VTP是一种消息协议，它使用第二层帧，<strong>在交换机之间传递VLAN信息</strong>，被称为VTP通告。<strong>有了VTP通告就可以再一台交换机上集中修改VLAN配置，所做的修改会被自动传播到网络中的其他交换机，从而实现VLAN配置的一致性。</strong></p>
<p>VTP域：也称为VLAN管理域，由一个以上共享VTP域名相连接的交换机组成。也就是说，VTP域是一组VTP域名相同并通过中继链路互相连接的交换机。使用VTP首先需要建立一个VTP管理域，在同一管理域中的交换机共享他们的VLAN信息，并且<strong>一个交换机只能参加一个VTP管理域</strong>。</p>
<p>配置VTP域的要求如下：</p>
<p>1、域内的每台交换机都必须使用相同的VTP域名。</p>
<p>2、交换机必须是相邻的，即相邻的交换机并具有相同的域名。</p>
<p>3、交换机之前必须配置中继链路(也就是Trunk)。</p>
<p>它不通告自己的VLAN配置信息，对收到的VTP通告只转发而不会学习与更改自己的VLAN信息。</p>
</blockquote>
<blockquote>
<p>VTP的模式</p>
<p>1、服务器模式：充当VTP服务器模式的交换机负责它所在域中VLAN信息的管理工作。VTP服务器可以创建、删除或修改VLAN，并向外发送VTP通告，同时，VTP服务器也会学习域名相同的VTP通告信息。</p>
<p>2、客户机模式：处于VTP客户机模式的交换机不允许管理创建，删除或修改VLAN。它们监听本域中其他交换机的VTP通告，并相应修改它们自己的VTP配置。</p>
<p>3、透明模式：VTP透明模式中的交换机不参与VTP。当交换机处于透明模式时，它可以创建，删除或修改本地的VLAN信息，但</p>
</blockquote>
<blockquote>
<p>VTP通告</p>
<p>使用VTP时，加入VTP域的每台交换机在其中继端口上通告如下信息：</p>
<p>1、管理域 (即VTP的域名信息)</p>
<p>2、版本号 (使用VTP的版本号，只要校验服务器和客户机模式的版本是否一致)</p>
<p>3、配置修改编号 (默认为0，当修改VTP域的配置之后，此编号会加1)</p>
<p>4、它所知道的VLAN (即VTP中的所有VLAN)</p>
<p>5、每个VLAN的某些参数 (vlan的相关信息)</p>
<p>注意：当一台修改编号高于此VTP域中的修改编号的交换机加入此VTP域时，此交换机的中的VLAN配置会覆盖所有VTP域中的VLAN配置，所以将交换机加入VTP域时要格外小心。我们可以将交换机的VTP模式改为透明模式，再改回服务器模式或交换机模式，或者是将交换机的域名更改一下在改回来，就可以将交换机的修改编号初始为0。</p>
</blockquote>
<blockquote>
<p>VTP修剪</p>
<p>VTP修剪是VTP的一个功能，它能减少中继链路上不必要的广播流量。</p>
</blockquote>
<blockquote>
<p>配置VTP实例</p>
<p>在配置VTP之前，我们需要将<strong>VTP服务器和VTP客户机之间的链路设置为中继链路</strong>。</p>
<p>列如：将Switch1和Switch2的24号端口设置为trunk中继链路。</p>
<p>Switch1(config)#int f0/24</p>
<p>Switch1(config)#switchport mode trunk</p>
<p>Switch1(config)#no sh</p>
<p>Switch2(config)#int f0/24</p>
<p>Switch2(config)#switchport mode trunk</p>
<p>Switch2(config)#no sh</p>
<p>配置VTP服务器模式</p>
<p>列如：将Switch1配置为VTP服务器，域名为test，秘密为123，配置VTP修剪。</p>
<p>Switch1#config terminal</p>
<p>Switch1(config)#vtp domain test</p>
<p>Switch1(config)#vtp mode server</p>
<p>SWitch1(config)#vtp passwd 123</p>
<p>Switch1(config)#vtp pruning</p>
<p>配置VTP客户机模式</p>
<p>列如：将Switch2配置为VTP客户机，域名和密码必须和服务器器一致，否则将不匹配。</p>
<p>Switch2#config terminal</p>
<p>Switch2(config)#vtp domain test</p>
<p>Switch2(config)#vtp mode client</p>
<p>SWitch2(config)#vtp passwd 123</p>
<p>Switch2(config)#vtp pruning</p>
<p>此时VTP服务器和VTP客户端就配置完成了，现在只需要在VTP服务器端创建VLAN，VTP客户端就可以自动学习到服务器端创建的VLAN，而不需要自己创建VLAN，但是注意，虽然VTP客户端可是自动学习VLAN，但是将端口加入VLAN的动作是不可以学习的，所以在客户端需要手动将端口添加到相应的VLAN中。</p>
</blockquote>
<blockquote>
<p>Unable to perform trunk negotiation on port Fa0/23 because of VTP domain mismatch这句话是什么意思？？是不能开启trunk在f0/23上！！因为VTP的域名错了！！你VTP配置的时候是不是名字有问题？？要就是配置一个！！要就是两边一样的！！不要两边不一样的！</p>
</blockquote>
<h2 id="实训2-多域OSPF"><a href="#实训2-多域OSPF" class="headerlink" title="实训2 多域OSPF"></a>实训2 多域OSPF</h2><pre class="line-numbers language-none"><code class="language-none">要求：
配置多域OSPF；
Loopback口相当于PC；
基本配置内容自主网络搜索。<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre>

<blockquote>
<p>OSPF多用于大型IPv4网络，是基于链路状态的路由协议，与基于距离矢量的路由协议相比具有更快的收敛速度，支撑的网络规模也更大。</p>
<p>OSPF（Open Shortest Path First）是IETF组织开发的一个基于链路状态的内部网关协议。目前针对IPv4协议使用的是OSPF Version 2（RFC2328）。OSPF是不属于任何一个厂商或组织私有的路由协议，使用Dijkstra的最短路径（SPF）算法计算路由。在OSPF中引入了区域的概念，有效的减少了路由选择协议对路由器CPU和内存的占用，同时也降低了路由选择协议的通信量，使得构建大型层次化网络成为可能</p>
</blockquote>
<blockquote>
<p><strong>duplex auto</strong> 是双工的协商模式为自动<br>双工模式有两种，一种是full（全双工），一种是half（半双工）<br><strong>speed auto</strong> 是速率为协商模式为自动<br>一般的100M口支持: 10M，100M和自动模式</p>
<p>选择为自动模式则接口会和对端设备的接口进行协商，并自动选择最佳模式。</p>
</blockquote>
<blockquote>
<p><strong>#ip access-group 10 out</strong></p>
<p>将列表10所定义的条件应用禁止从此接口出去</p>
<p>该命令的详细说明如下：<br>ip access-group {[access-list-number] |[ name]} [in | out]<br>no ip access-group {[access-list-number] |[ name]} [in | out]</p>
<p>功能：将指定的访问列表应用到相关接口，并且指定acl起作用的方向。本命令的no操作为解除访问列表应用到相关接口，若没有指定方向，则默认为out；<br>若没有指定具体的[access-list-number] 或[name]而指定了方向，则默认为删除该方向上所有的访问列表的应用；若没有指定具体的[access-list-number] 或[name]也没有指定方向，则默认为删除out方向上所有的访问列表的应用。</p>
<p>参数：[access-list-number]为访问表表号，取值范围1～199；[name]为由ip access-list 命令指定的访问表名字，最长不超过8个字符；in为过滤入口的包；out为过滤出口的包。</p>
<p>缺省情况：没有任何访问表被应用至任何接口。若指定了绑定，而未指定方向，缺省为out。</p>
<p>命令模式：接口配置模式</p>
<p>使用指南：在访问列表应用到具体接口的具体方向之前，访问列表的规则是不起作用的。每个接口定义两个方向，即in和out方向。前者代表流入接口的方向，<br>后者代表流出接口的方向。规则可单独对in或out方向起作用，即只过滤入口的包或只过滤出口方向上的包，也可以两个方向都过滤。</p>
<p>应用到接口上的访问列表可以有多条，但只能有一条标准访问列表，对扩展访问列表来说，一个接口一个方向相同协议的访问列表只能有一条。访问列表的协议是指</p>
<p>每个表的协议缺省为这个表的第一条规则中指定要过滤的协议。若通过的信息包符合多条规则，则只有匹配的第一条规则有作用，匹配的顺序与规则应用到接口的先<br>后顺序一致。若规则中含有相互冲突的设置，以第一条匹配到的规则为准。</p>
<p>在当前时间不在分段时间过滤访问表设定的时间段时，将分段时间过滤访问表应用到接口是不起作用的，但等时间进入设定的时间段后，曾经应用到接口的分段时间过滤访问表会自动生效。</p>
</blockquote>
<p><img src="https://img-blog.csdn.net/20160629191708718?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="img"></p>
<blockquote>
<p><strong>router ospf 10</strong></p>
<p>Router ospf 10 中的 10 是这台<a target="_blank" rel="noopener" href="https://so.csdn.net/so/search?q=%E8%B7%AF%E7%94%B1%E5%99%A8&spm=1001.2101.3001.7020">路由器</a> Ospf 进程的 ID 号！<br>路由器和我们的PC一样，是多任务系统，理论上能够支持多个 OSPF 进程同时运行！此ID号仅本地有效！ <a target="_blank" rel="noopener" href="https://so.csdn.net/so/search?q=SNMP&spm=1001.2101.3001.7020">SNMP</a> 是网络管理协议，OSPF<br>是路由协议，两者就不是一个东西，不能相提并论！</p>
<p><strong>log-adjacency-changes</strong></p>
<p><strong>log-adjacency-changes命令</strong>可用来激活路由协议邻接关系变化日志的功能（例如ospf或者ISIS等）。使用该命令来生成SYSLOG信息以用于网络操作与管理。日志信息对于故障排除也非常有用。log-adjacency-changes 是一个日志开关，意思是<strong>当 OSPF 探测到邻居关系发生变化时，将变化情况记录在系统日志里面</strong>！</p>
<p><strong>network 192.168.233.160 0.0.0.3 area 1</strong></p>
<pre class="line-numbers language-none"><code class="language-none">network 192.168.233.164 0.0.0.3 area 1 
network 192.168.233.168 0.0.0.3 area 1 
network 192.168.233.172 0.0.0.3 area 1 
network 192.168.233.176 0.0.0.3 area 1 
network 192.168.233.184 0.0.0.3 area 1 
network 192.168.233.188 0.0.0.3 area 1 
network 192.168.233.192 0.0.0.3 area 1 
network 192.168.233.196 0.0.0.3 area 1 
network 192.168.233.200 0.0.0.3 area 1 
network 192.168.233.204 0.0.0.3 area 1
network 10.228.1.0      0.0.0.15 area 1 <span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p>是使用 OSPF 向邻居发布路由信息！ area 1 是 OSPF路由域中的 区域1，ospf 路由域分为骨干区域和非骨干区域，只有 area 0 是骨干区域，其他都是非骨干区域！<br>0.0.0.3表示： 反掩码，表示匹配反掩码为1的位<br>0.0.0.255实际上是0.0.0.1111 1111 只要192.168.2.xxxx xxxx的网段就应用该路由 我自己把反掩码中的0理解为固定位，1理解为自由位。固定位就是不能变的，自由位是能变的，其实就是对前面ip的修饰，固定位就是他的网络段</p>
<p>原文链接：<a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_31828929/article/details/71191679">https://blog.csdn.net/qq_31828929/article/details/71191679</a></p>
</blockquote>
<pre class="line-numbers language-c" data-language="c"><code class="language-c">PC与路由器的接口配置：
interface FastEthernet0<span class="token operator">/</span><span class="token number">0</span>
 
ip address <span class="token number">192.168</span><span class="token number">.1</span><span class="token number">.254</span> <span class="token number">255.255</span><span class="token number">.255</span><span class="token number">.0</span>
 
duplex <span class="token keyword">auto</span>
    
speed <span class="token keyword">auto</span>
    
<span class="token punctuation">[</span><span class="token punctuation">(</span><span class="token number">30</span>条消息<span class="token punctuation">)</span> 思科实验之配置ACL_晚风挽着浮云的博客<span class="token operator">-</span>CSDN博客_思科配置acl<span class="token punctuation">]</span><span class="token punctuation">(</span>https<span class="token operator">:</span><span class="token comment">//blog.csdn.net/weixin_57636278/article/details/123912132)</span>
                                              
interface FastEthernet0<span class="token operator">/</span><span class="token number">0</span>
ip address <span class="token number">192.168</span><span class="token number">.1</span><span class="token number">.254</span> <span class="token number">255.255</span><span class="token number">.255</span><span class="token number">.0</span>
no shutdown
exit                                              <span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<pre class="line-numbers language-c" data-language="c"><code class="language-c">R1<span class="token operator">:</span>
interface GigabitEthernet0<span class="token operator">/</span><span class="token number">0</span>
 ip address <span class="token number">172.16</span><span class="token number">.10</span><span class="token number">.1</span> <span class="token number">255.255</span><span class="token number">.255</span><span class="token number">.0</span>
 no shutdown                          #开启接口
exit
router ospf <span class="token number">10</span>                        #开启ospf 进程号为<span class="token number">10</span>
network <span class="token number">172.16</span><span class="token number">.10</span><span class="token number">.0</span> <span class="token number">0.0</span><span class="token number">.0</span><span class="token number">.255</span> area <span class="token number">1</span>  #宣告直连的网段；网段的反掩码；其直连的网段属于area1区域
R2<span class="token operator">:</span>
interface GigabitEthernet0<span class="token operator">/</span><span class="token number">0</span>
 ip address <span class="token number">172.16</span><span class="token number">.10</span><span class="token number">.2</span> <span class="token number">255.255</span><span class="token number">.255</span><span class="token number">.0</span>
 no shu
interface GigabitEthernet0<span class="token operator">/</span><span class="token number">1</span>
 ip address <span class="token number">172.16</span><span class="token number">.20</span><span class="token number">.1</span> <span class="token number">255.255</span><span class="token number">.255</span><span class="token number">.0</span>
 no shu
 exit
router ospf <span class="token number">10</span>
 network <span class="token number">172.16</span><span class="token number">.10</span><span class="token number">.0</span> <span class="token number">0.0</span><span class="token number">.0</span><span class="token number">.255</span> area <span class="token number">1</span>  #宣告直连，其直连的网段属于area1 区域
 network <span class="token number">172.16</span><span class="token number">.20</span><span class="token number">.0</span> <span class="token number">0.0</span><span class="token number">.0</span><span class="token number">.255</span> area <span class="token number">0</span>  #area0是骨干区域
 R3：
 interface GigabitEthernet0<span class="token operator">/</span><span class="token number">0</span>
 ip address <span class="token number">172.16</span><span class="token number">.20</span><span class="token number">.2</span> <span class="token number">255.255</span><span class="token number">.255</span><span class="token number">.0</span>
 no shu
interface GigabitEthernet0<span class="token operator">/</span><span class="token number">1</span>
 ip address <span class="token number">172.16</span><span class="token number">.30</span><span class="token number">.1</span> <span class="token number">255.255</span><span class="token number">.255</span><span class="token number">.0</span>
 no shu
 exit
router ospf <span class="token number">10</span>
 network <span class="token number">172.16</span><span class="token number">.20</span><span class="token number">.0</span> <span class="token number">0.0</span><span class="token number">.0</span><span class="token number">.255</span> area <span class="token number">0</span>
 network <span class="token number">172.16</span><span class="token number">.30</span><span class="token number">.0</span> <span class="token number">0.0</span><span class="token number">.0</span><span class="token number">.255</span> area <span class="token number">2</span>
 R4：
 interface GigabitEthernet0<span class="token operator">/</span><span class="token number">0</span>
 ip address <span class="token number">172.16</span><span class="token number">.30</span><span class="token number">.2</span> <span class="token number">255.255</span><span class="token number">.255</span><span class="token number">.0</span>
 no shu
 exit
router ospf <span class="token number">10</span>
 network <span class="token number">172.16</span><span class="token number">.30</span><span class="token number">.0</span> <span class="token number">0.0</span><span class="token number">.0</span><span class="token number">.255</span> area <span class="token number">2</span>
 
 show ip route
 ping <span class="token number">172.16</span><span class="token number">.30</span><span class="token number">.2</span>
    
 https<span class="token operator">:</span><span class="token comment">//blog.csdn.net/zhangzc0408/article/details/124372279</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<blockquote>
<p> <strong>Loopback</strong>是路由器里面的一个逻辑接口。逻辑接口是指能够实现数据交换功能，但是物理上不存在、需要通过配置建立的接口。Loopback接口一旦被创建，其物理状态和链路协议状态永远是Up，即使该接口上没有配置IP地址</p>
<p>Loopback接口创建后一直保持UP状态，用户可通过配置Loopback接口达到提高网络可靠性的目的。</p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/JackLiu16/article/details/80296461">(30条消息) Loopback接口的主要作用及Loopback端口配置_JackLiu16的博客-CSDN博客_交换机loopback接口</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.51cto.com/u_15624911/5287875">OSPF多域配置_wx627255bd4ac6d的技术博客_51CTO博客</a></p>
</blockquote>
<h2 id="实训3-路由交换综合"><a href="#实训3-路由交换综合" class="headerlink" title="实训3 路由交换综合"></a>实训3 路由交换综合</h2><pre class="line-numbers language-none"><code class="language-none">实训要求
1.试验台环境：路由器为2811，交换机3560、2950；
2.规划IP，配置接口，启动静态或动态路由协议，保障网络连通性；
3.划分两个VLAN，VLAN 10采用192.168.10.0&#x2F;24，VLAN 20采用192.168.20.20；
4.能够实现VLAN间路由；
5.禁止VLAN 20中的主机访问WWW服务，但不禁止Ping （VLAN10中主机可以访问WWW）。
6.VLAN 20需要配置DHCP。<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p><img src="https://img-blog.csdnimg.cn/20200723091948207.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0MDE4Njky,size_16,color_FFFFFF,t_70#pic_center" alt="在这里插入图片描述"></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_44018692/article/details/107529914">(30条消息) 交换机与路由器的通信的配置（2020.7.15）_penguinhd的博客-CSDN博客</a></p>
<blockquote>
<p>SW13</p>
<p>Enable<br>Conf t<br>Vlan 10<br>Exit<br>Interface f0/1<br>Switchport access vlan 10<br>Exit<br>Interface f0/2<br>Switchport mode trunk </p>
</blockquote>
<blockquote>
<p>sw14</p>
<p>Enable<br>Conf t<br>Vlan 20<br>Exit<br>Interface f0/2<br>Switchport access vlan 20<br>Exit<br>Interface f0/1<br>Switchport mode trunk</p>
</blockquote>
<blockquote>
<p>sw12</p>
<p>enable<br>conf t<br>vlan 10<br>exit<br>vlan 20<br>interface range f0/1-3<br>switchport mode trunk </p>
</blockquote>
<blockquote>
<p>sw1</p>
<p>enable<br>conf t<br>vlan 10<br>exit<br>vlan 20<br>exit<br>interface f0/1<br>switchport tr en do<br>switchport mode trunk<br>exit<br>interface vlan 10<br>ip address 192.168.10.1 255.255.255.0<br>exit<br>interface vlan 20<br>ip address 192.168.20.1 255.255.255.0<br>exit<br>ip routing</p>
<p>Switch(config)#interface f0/2<br>Switch(config-if)#no switchport（使其成为路由器接口）<br>Switch(config-if)#ip address 192.168.30.1 255.255.255.0</p>
</blockquote>
<blockquote>
<p>route 4</p>
<p>enable<br>config t<br>interface f0/0<br>no shutdown<br>ip address 192.168.30.2 255.255.255.0<br>exit<br>interface f0/1<br>no shutdown<br>ip address 192.168.40.1 255.255.255.0</p>
</blockquote>
<blockquote>
<p>route 5</p>
<p>enable<br>conf t<br>interface f0/0<br>no shutdown<br>ip address 192.168.40.2 255.255.255.0<br>exit<br>interface f0/1<br>no shutdown<br>ip address 192.168.50.1 255.255.255.0</p>
</blockquote>
<blockquote>
<p><strong>什么是ACL？</strong></p>
<p>ACL全称访问控制列表（Access Control List），主要通过配置一组规则进行过滤路由器或交换机接口进出的数据包，</p>
<p>是<strong>控制访问的一种网络技术手段</strong>， ACL适用于所有的被路由支持的协议，如IP、tcp、udp、ftp、www等。</p>
<p><strong>什么是反掩码？</strong></p>
<p>反掩码就是通配符掩码 ， 通过标记0和1告诉设备应该匹配到哪位。 在反掩码中，相应位为1的地址在比较中忽略，</p>
<p>为0的必须被检查。IP地址与反掩码都是32位的数 由于跟子网掩码刚好相反，所以也叫反掩码 。</p>
<p>路由器使用的通配符掩码与源或目标地址一起来分辨匹配的地址范围，它与子网掩码不同。它不像子网掩码告诉</p>
<p>路由器IP地址是属于哪个子网（网段），通配符掩码告诉路由器为了判断出匹配，它需要检查IP地址中的多少位。</p>
<p>例如：</p>
<p>255.255.255.0 反掩码（wildcard-mask）就是0.0.0.255</p>
<p>255.255.255.248 反掩码（wildcard-mask）就是0.0.0.7</p>
<p><strong>ACL工作原理：</strong></p>
<p>ACL使用包过滤技术，在路由器上读取OSI七层模型的第3层和第4层包头中的信息。如源地址，目标地址，源端口，目标端口等，根据预先定义好的规则，对包进行过滤，从而达到访问控制的目的。</p>
<p>对于路由器接口而言，ACL是有两个方向：</p>
<p><strong>注意：</strong>如果发现没有匹配的ACL规则，默认会丢弃该数据包，思科ACL规则默认会有一条隐藏的deny any any规则，而华三ACL规则默认是permit any any规则。</p>
<p>**入站—-**如果是入站访问列表，则当路由器接收到数据包时，Cisco IOS 软件将检查访问列表中的条件语句，看是否有匹配。如果数据包被允许，则软件将继续处理该数据包。如果数据包被拒绝，则软件会丢弃该数据包。</p>
<p>**出站—-**如果是出站访问列表，则当软件到接收数据包并将群其路由至出站接口后，软件将检查访问列表中的条件语句，看是否有匹配。如果数据包被允许，则软件会发送该数据包。如果数据包被拒绝，则软件会丢弃该数据包。</p>
<p><img src="https://images2018.cnblogs.com/blog/435896/201805/435896-20180516175614455-864140199.png" alt="img"></p>
<p><strong>ACL两种类型：</strong></p>
<p><strong>标注：</strong>允许在标准ACL和扩展ACL中使用名称代替访问控制列表号。</p>
<p><strong>1、 标准的ACL</strong></p>
<p>根据数据包的源IP地址来控制允许转发或拒绝数据包，访问控制列表号1~99。</p>
<p>标准访问控制列表配置命令如下：</p>
<p>Router(config)#access-list access-list-number {permit|deny} source [souce-wildcard]</p>
<p>或者</p>
<p>Router(config)#ip access-list standard access-list-number</p>
<p>Router(config-std-nacl)#Sequence Number{permit|deny} source [souce-wildcard]</p>
<p>下面是命令参数的详细说明</p>
<p>access-list-number：访问控制列表号，标准ACL取值是1-99，可以使用名称替代列表号。</p>
<p>Sequence Number：每条ACL规则列表序列号，可使用范围1-2147483647。</p>
<p>permit | deny：如果满足规则，则允许/拒绝通过。</p>
<p>source：数据包的源地址，可以是主机地址，也可以是网络地址</p>
<p><strong>2、 扩展的ACL</strong></p>
<p>根据数据包的源IP地址、目的IP地址、指定协议，端口、标志和时间来控制允许转发或拒绝数据包，访问控制列表号100~199</p>
<p>扩展访问控制列表配置命令如下：</p>
<p>Router(config)#access-list access-list-number {permit|deny} protocol {source souce-wildcard destination destination-wildcard} [operator operan]</p>
<p>或者</p>
<p>Router(config)#ip access-list extended access-list-number</p>
<p>Router(config-std-nacl)#{permit|deny} protocol {source souce-wildcard destination destination-wildcard} [operator operan]</p>
<p>下面是命令参数的详细说明</p>
<p>access-list-number：访问控制列表号，扩展ACL取值100-199，可以使用名称替代列表号。</p>
<p>Sequence Number：每条ACL规则列表序列号，可使用范围1-2147483647。</p>
<p>permit|deny：如果满足规则，则允许/拒绝通过。</p>
<p>protocol：用来指定协议的类型，如IP，TCP，UDP，ICMP等。</p>
<p>source、destination：源和目的，分别用来标示源地址和目的地址。</p>
<p>souce-wildcard、destination-wildcard：子网反码，souce-wildcard是源反码，destination-wildcard是目标反码。</p>
<p>operator operan：lt(小于)、gt(大于)、eq(等于)、neq(不等于)、rand(范围端口号)等。</p>
</blockquote>
<blockquote>
<p><strong>DHCP</strong></p>
<p>​    DHCP全称为Dynamic Host Configuration Protocol，中文含义为“动态主机配置协议”，通常被应用在大型的局域网络环境中，主要作用是集中管理、分配IP地址，使网络环境中的主机动态获得IP地址、Gateway地址、<a target="_blank" rel="noopener" href="https://product.pconline.com.cn/itbk/wlbg/network/1305/3304121.html">DNS</a>服务器地址等信息，并能够提升地址的使用率。</p>
<p>　DHCP协议采用客户端/服务器模型，主机地址的动态分配任务由网络主机驱动。当DHCP服务器接收到来自网络主机申请地址的信息时，才会向网络主机发送相关的地址配置等信息，以实现网络主机地址信息的动态配置。</p>
<p>​    <strong>DHCP服务器</strong>就是自动给电脑分配IP地址和子网掩码的服务器。比如我们设置了路由器的DHCP服务器，让DHCP服务器自动分配IP地址，从<a target="_blank" rel="noopener" href="https://product.pconline.com.cn/itbk/wlbg/network/1403/4387067.html">192.168.1.1</a>00到192.168.1.199(子网掩码会自动设置，我们无需设置)。</p>
</blockquote>
<h2 id="实训4-RIP一般配置方法"><a href="#实训4-RIP一般配置方法" class="headerlink" title="实训4 RIP一般配置方法"></a>实训4 RIP一般配置方法</h2><blockquote>
<p>RIP（Routing　Information protocol) 路由信息协议.<br>是一种内部网关协议（IGP），是一种动态路由选择协议，用于自治系统（AS）内的路由信息的传递。RIP协议基于距离矢量算法（DistanceVectorAlgorithms），使用“跳数”(即metric)来衡量到达目标地址的路由距离。RIP通过UDP报文进行路由信息交换,使用的端口号为520.</p>
<p>这种协议的路由器<strong>只关心自己周围的世界，只与自己相邻的路由器交换信息，范围限制在15跳(15度)之内</strong>，再远，它就不关心了。RIP应用于OSI网络七层模型的应用层。各厂家定义的管理距离（AD，即优先级）如下：华为定义的优先级是100，思科定义的优先级是120。</p>
</blockquote>
<blockquote>
<p>第一步：将每个设备的IP地址配好</p>
<p>Router#configure terminal<br>Enter configuration commands, one per line.  End with CNTL/Z.<br>Router(config)#interface g0/0<br>Router(config-if)#ip address 192.168.1.1 255.255.255.0<br>Router(config-if)#no shutdown<br>Router(config-if)#exit<br>Router(config)#interface Se0/3/0<br>Router(config-if)#ip address 10.0.0.1 255.0.0.0<br>Router(config-if)#no shutdown<br>Router(config-if)#end<br>Router#<br>%SYS-5-CONFIG_I: Configured from console by console</p>
<p>Router#</p>
</blockquote>
<blockquote>
<p>第二步：配置rip路由</p>
<p>Router(config)#hostname R0<br>R0(config)#end<br>R0#<br>%SYS-5-CONFIG_I: Configured from console by console<br>R0#configure terminal<br>Enter configuration commands, one per line.  End with CNTL/Z.<br>R0(config)#route rip<br>R0(config-router)#network 192.168.1.0<br>R0(config-router)#network 10.0.0.0<br>R0(config-router)#end</p>
</blockquote>
<h2 id="实训5-华为交换初步"><a href="#实训5-华为交换初步" class="headerlink" title="实训5 华为交换初步"></a>实训5 华为交换初步</h2><pre class="line-numbers language-none"><code class="language-none">实训目的：
了解VLAN的划分方法；
了解VLAN特性；
了解Trunk的配置方法<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre>

<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/sizaif/article/details/78281112">(30条消息) 二层交换机实现vlan 功能 (Cisco Packer Tracer 模拟器)_sizaif的博客-CSDN博客</a></p>
<p><img src="https://img-blog.csdn.net/20171019103159363?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2l6YWlm/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="img"></p>
<blockquote>
<p>主机配置：</p>
<p>Switch&gt;en<br>Switch#conf<br>Switch(config)#vlan 10 // 创建 vlan 10<br>Switch(config-vlan)#vlan 20 // 创建 vlan 20<br>Switch(config-vlan)#EXIT<br>Switch(config-if)#interface fa0/1  // 进入端口 f0/1 并配置为接入到vlan10 的access 模式<br>Switch(config-if)#switchport mode access<br>Switch(config-if)#switchport  access  vlan 10<br>Switch(config-if)#interface fa0/2  //进入端口 f0/2 并配置为接入到vlan20 的access 模式<br>Switch(config-if)#switchport mode access<br>Switch(config-if)#switchport  access  vlan 20</p>
</blockquote>
<blockquote>
<p>交换机配置：</p>
<p>Switch&gt;en<br>Switch#conf<br>Switch(config)#interface fa0/24 // 进入端口f0/24  并设置为trun 模式，允许所以vlan通过<br>Switch(config-if)#switchport mode access<br>Switch(config-if)#switchport mode trunk<br>Switch(config-if)#switchport trunk allowed vlan all</p>
</blockquote>
<p>192.168.1.1 —– &gt;ping 192.168.2.2 <strong>ping不通  ：同一交换机下，不同vlan，不同网段</strong><img src="https://img-blog.csdn.net/20171019103514241?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2l6YWlm/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="img"></p>
<p>192.168.1.1 —– &gt; ping 192.168.1.4 <strong>ping通： 跨交换机，同一vlan，同一网段</strong></p>
<p><img src="https://img-blog.csdn.net/20171019103517139?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2l6YWlm/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="img"></p>
<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><pre class="line-numbers language-c" data-language="c"><code class="language-c">Switch#show ip route
Switch#show vlan
Switch#write #保存已写的内容
    
PC<span class="token operator">></span>ipconfig IP
PC<span class="token operator">></span>ping <span class="token number">192.168</span><span class="token number">.2</span><span class="token number">.2</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p><img src="https://zhang2002gz.oss-cn-qingdao.aliyuncs.com/img/image-20220903230622353.png" alt="image-20220903230622353"></p>
<pre class="line-numbers language-c" data-language="c"><code class="language-c">二层交换机
Switch<span class="token operator">></span>en
Switch#conf t

#设置vlan    
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span>#vlan <span class="token number">2</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span>#vlan <span class="token number">3</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span>vlan<span class="token punctuation">)</span>#exit

#同一个vlan交流，配置vlan就用switchport access vlan n就足够了
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span>#<span class="token keyword">int</span> fa <span class="token number">0</span><span class="token operator">/</span><span class="token number">2</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#switchport access vlan <span class="token number">2</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#<span class="token keyword">int</span> fa <span class="token number">0</span><span class="token operator">/</span><span class="token number">3</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#switchport access vlan <span class="token number">3</span>
#想vlan2和vlan3交流就得使用trunk协议，二层交换机上配置如下：
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#<span class="token keyword">int</span> fa <span class="token number">0</span><span class="token operator">/</span><span class="token number">1</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#switchport mode trunk
  
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#end<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<pre class="line-numbers language-c" data-language="c"><code class="language-c">三层交换机
Switch<span class="token operator">></span>en
Switch#conf t

<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span>#vlan <span class="token number">2</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span>#vlan <span class="token number">3</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span>vlan<span class="token punctuation">)</span>#exit

#三层交换机口配置    
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span>#<span class="token keyword">int</span> fa <span class="token number">0</span><span class="token operator">/</span><span class="token number">1</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#switchport trunk encapsulation dot1q
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#switchport mode trunk
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#switchport trunk allowed vlan <span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#exit

#启动vlan n的使用
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span>#<span class="token keyword">int</span> vlan <span class="token number">2</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#ip address <span class="token number">192.168</span><span class="token number">.1</span><span class="token number">.1</span> <span class="token number">255.255</span><span class="token number">.255</span><span class="token number">.0</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#no shutdown
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#exit
（vlan <span class="token number">3</span> 同理）

#开启三层交换机默认路由
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span>#ip routing
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span>#exit<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<pre class="line-numbers language-c" data-language="c"><code class="language-c">##配置VTP服务器https<span class="token operator">:</span><span class="token comment">//www.cnblogs.com/zoulongbin/p/9047390.html</span>
#三层交换机实现服务器
Switch<span class="token operator">></span>enable
Switch#vlan database
<span class="token function">Switch</span><span class="token punctuation">(</span>vlan<span class="token punctuation">)</span>#vtp domain CCTV
<span class="token function">Switch</span><span class="token punctuation">(</span>vlan<span class="token punctuation">)</span>#vtp server
    
##创建VLAN
<span class="token function">Switch</span><span class="token punctuation">(</span>vlan<span class="token punctuation">)</span>#vlan <span class="token number">10</span> name VLAN10
<span class="token function">Switch</span><span class="token punctuation">(</span>vlan<span class="token punctuation">)</span>#vlan <span class="token number">20</span> name VLAN20
<span class="token function">Switch</span><span class="token punctuation">(</span>vlan<span class="token punctuation">)</span>#exit
    
##配置VLAN IP地址
Switch#configure terminal
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span>#interface vlan <span class="token number">10</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#ip address <span class="token number">192.168</span><span class="token number">.10</span><span class="token number">.1</span> <span class="token number">255.255</span><span class="token number">.255</span><span class="token number">.0</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#exit
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span>#interface vlan <span class="token number">20</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#ip address <span class="token number">192.168</span><span class="token number">.20</span><span class="token number">.1</span> <span class="token number">255.255</span><span class="token number">.255</span><span class="token number">.0</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#exit
    
##开启三层交换机默认路由
<span class="token number">3560</span>SW<span class="token punctuation">(</span>config<span class="token punctuation">)</span>#ip routing
    
#设置端口汇聚<span class="token punctuation">(</span>trunk<span class="token punctuation">)</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span>#interface range fastEthernet <span class="token number">0</span><span class="token operator">/</span><span class="token number">22</span><span class="token operator">-</span><span class="token number">24</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token operator">-</span>range<span class="token punctuation">)</span>#switchport trunk encapsulation dot1q
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token operator">-</span>range<span class="token punctuation">)</span>#switchport mode trunk
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token operator">-</span>range<span class="token punctuation">)</span>#no shutdown
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token operator">-</span>range<span class="token punctuation">)</span>#exit<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<pre class="line-numbers language-c" data-language="c"><code class="language-c">#二层交换机作为VTP客户端
Switch#vlan database
<span class="token function">Switch</span><span class="token punctuation">(</span>vlan<span class="token punctuation">)</span>#vtp domain CCTV
<span class="token function">Switch</span><span class="token punctuation">(</span>vlan<span class="token punctuation">)</span>#vtp client
<span class="token function">Switch</span><span class="token punctuation">(</span>vlan<span class="token punctuation">)</span>#exit
    
##设置端口汇聚<span class="token punctuation">(</span>trunk<span class="token punctuation">)</span>
Switch#configure terminal
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span>#interface fastEthernet <span class="token number">0</span><span class="token operator">/</span><span class="token number">24</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#switchport mode trunk
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#no shutdown
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#exit
    
##分配VLAN所属端口
Switch#configure terminal
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span>#interface range fastEthernet <span class="token number">0</span><span class="token operator">/</span><span class="token number">1</span><span class="token operator">-</span><span class="token number">5</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token operator">-</span>range<span class="token punctuation">)</span>#switchport access vlan <span class="token number">10</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token operator">-</span>range<span class="token punctuation">)</span>#switchport mode access
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token operator">-</span>range<span class="token punctuation">)</span>#no shutdown
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token operator">-</span>range<span class="token punctuation">)</span>#exit<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p><img src="https://zhang2002gz.oss-cn-qingdao.aliyuncs.com/img/image-20220903233009617.png" alt="image-20220903233009617"></p>
<pre class="line-numbers language-c" data-language="c"><code class="language-c"><span class="token macro property"><span class="token directive-hash">#</span><span class="token expression">PC机与路由器间的配置：</span></span>
<span class="token function">Router</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#interface FastEthernet0<span class="token operator">/</span><span class="token number">0</span>
<span class="token function">Router</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#ip address <span class="token number">192.168</span><span class="token number">.1</span><span class="token number">.254</span> <span class="token number">255.255</span><span class="token number">.255</span><span class="token number">.0</span>
<span class="token function">Router</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#no shutdown
<span class="token function">Router</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#exit  <span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<pre class="line-numbers language-c" data-language="c"><code class="language-c">#路由器与路由器间的配置
<span class="token function">Router</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#interface GigabitEthernet0<span class="token operator">/</span><span class="token number">0</span>
<span class="token function">Router</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#ip address <span class="token number">172.16</span><span class="token number">.10</span><span class="token number">.1</span> <span class="token number">255.255</span><span class="token number">.255</span><span class="token number">.0</span>
<span class="token function">Router</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#no shutdown                          
<span class="token function">Router</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#exit
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">ospf</span><span class="token expression">配置</span></span>
<span class="token function">Router</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span>#router ospf <span class="token number">10</span>                        
<span class="token function">Router</span><span class="token punctuation">(</span>config<span class="token operator">-</span>router<span class="token punctuation">)</span>#network <span class="token number">172.16</span><span class="token number">.10</span><span class="token number">.0</span> <span class="token number">0.0</span><span class="token number">.0</span><span class="token number">.255</span> area <span class="token number">1</span> <span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<pre class="line-numbers language-c" data-language="c"><code class="language-c">#配置loopback接口（ip自定义）
<span class="token function">Router</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span>#interface loopback <span class="token number">0</span>
<span class="token function">Router</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#ip address <span class="token number">1.1</span><span class="token number">.1</span><span class="token number">.1</span> <span class="token number">255.255</span><span class="token number">.255</span><span class="token number">.255</span>
<span class="token function">Router</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#no shutdown
<span class="token function">Router</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span>#interface loopback <span class="token number">1</span>
<span class="token function">Router</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#ip address <span class="token number">192.168</span><span class="token number">.1</span><span class="token number">.1</span> <span class="token number">255.255</span><span class="token number">.255</span><span class="token number">.0</span>
<span class="token function">Router</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#no shutdown<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p><img src="https://zhang2002gz.oss-cn-qingdao.aliyuncs.com/img/image-20220903233645910.png" alt="image-20220903233645910"></p>
<pre class="line-numbers language-c" data-language="c"><code class="language-c">#路由器地址配置
<span class="token function">Router</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span>#interface g0<span class="token operator">/</span><span class="token number">0</span>
<span class="token function">Router</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#ip address <span class="token number">192.168</span><span class="token number">.1</span><span class="token number">.1</span> <span class="token number">255.255</span><span class="token number">.255</span><span class="token number">.0</span>
<span class="token function">Router</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#no shutdown
<span class="token function">Router</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#exit<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<pre class="line-numbers language-c" data-language="c"><code class="language-c">#路由器RIP配置
<span class="token function">Router</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span>#hostname R0
<span class="token function">R0</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span>#route rip
<span class="token function">R0</span><span class="token punctuation">(</span>config<span class="token operator">-</span>router<span class="token punctuation">)</span>#network <span class="token number">192.168</span><span class="token number">.1</span><span class="token number">.0</span>
<span class="token function">R0</span><span class="token punctuation">(</span>config<span class="token operator">-</span>router<span class="token punctuation">)</span>#network <span class="token number">10.0</span><span class="token number">.0</span><span class="token number">.0</span>
<span class="token function">R0</span><span class="token punctuation">(</span>config<span class="token operator">-</span>router<span class="token punctuation">)</span>#end<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p><img src="https://zhang2002gz.oss-cn-qingdao.aliyuncs.com/img/image-20220903234041573.png" alt="image-20220903234041573"></p>
<pre class="line-numbers language-c" data-language="c"><code class="language-c">主机的vlan配置：
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span>#vlan <span class="token number">10</span>  
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span>vlan<span class="token punctuation">)</span>#EXIT

<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#interface fa0<span class="token operator">/</span><span class="token number">1</span> 
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#switchport mode access 
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#switchport access vlan <span class="token number">10</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<pre class="line-numbers language-c" data-language="c"><code class="language-c">二层交换机间的配置：
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span>#interface fa0<span class="token operator">/</span><span class="token number">24</span> 
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#switchport mode access 
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#switchport mode trunk 
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#switchport trunk allowed vlan all<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p><img src="https://zhang2002gz.oss-cn-qingdao.aliyuncs.com/img/image-20220904091713476.png" alt="image-20220904091713476"></p>
<pre class="line-numbers language-c" data-language="c"><code class="language-c">路由器与交换机间的配置：
（<span class="token number">1</span>）交换机端口配置
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">f</span><span class="token expression"><span class="token number">0</span><span class="token operator">/</span><span class="token number">1</span>协议配置</span></span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span>#interface f0<span class="token operator">/</span><span class="token number">1</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#switchport trunk encapsulation dot1q
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#switchport mode trunk
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#exit

<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">f</span><span class="token expression"><span class="token number">0</span><span class="token operator">/</span><span class="token number">1</span> IP配置</span></span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span>#interface f0<span class="token operator">/</span><span class="token number">1</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#no switchport（使其成为路由器接口） 
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#ip address <span class="token number">192.168</span><span class="token number">.30</span><span class="token number">.1</span> <span class="token number">255.255</span><span class="token number">.255</span><span class="token number">.0</span>

（<span class="token number">2</span>）路由器配置
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span>#interface f0<span class="token operator">/</span><span class="token number">0</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#no shutdown
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#ip address <span class="token number">192.168</span><span class="token number">.30</span><span class="token number">.2</span> <span class="token number">255.255</span><span class="token number">.255</span><span class="token number">.0</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token operator">-</span><span class="token keyword">if</span><span class="token punctuation">)</span>#exit<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<pre class="line-numbers language-c" data-language="c"><code class="language-c"><span class="token macro property"><span class="token directive-hash">#</span><span class="token expression">DHCP<span class="token operator">:</span>动态地址获取</span></span>
<span class="token function">Switch</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span>#ip dhcp pool vlan20
<span class="token function">Switch</span><span class="token punctuation">(</span>dhcp<span class="token operator">-</span>config<span class="token punctuation">)</span>#network <span class="token number">192.168</span><span class="token number">.20</span><span class="token number">.254</span> <span class="token number">255.255</span><span class="token number">.255</span><span class="token number">.0</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>dhcp<span class="token operator">-</span>config<span class="token punctuation">)</span>#<span class="token keyword">default</span><span class="token operator">-</span>router <span class="token number">192.168</span><span class="token number">.20</span><span class="token number">.254</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>dhcp<span class="token operator">-</span>config<span class="token punctuation">)</span>#dns<span class="token operator">-</span>server <span class="token number">8.8</span><span class="token number">.8</span><span class="token number">.8</span>
<span class="token function">Switch</span><span class="token punctuation">(</span>dhcp<span class="token operator">-</span>config<span class="token punctuation">)</span>#end

<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">telnet</span><span class="token expression"><span class="token operator">:</span>远程登陆</span></span>
Switch（config）#enable password <span class="token number">123</span>
Switch（config）# line vty <span class="token number">0</span> <span class="token number">2</span>
Switch（config<span class="token operator">-</span>line）# password cisco<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p><img src="https://zhang2002gz.oss-cn-qingdao.aliyuncs.com/img/image-20220904144443585.png" alt="image-20220904144443585"></p>

                
            </div>
            <hr/>

            

    <div class="reprint" id="reprint-statement">
        
            <div class="reprint__author">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-user">
                        文章作者:
                    </i>
                </span>
                <span class="reprint-info">
                    <a href="/shier_jinghuang/about" rel="external nofollow noreferrer">十二惊惶</a>
                </span>
            </div>
            <div class="reprint__type">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-link">
                        文章链接:
                    </i>
                </span>
                <span class="reprint-info">
                    <a href="https://im-so-scared-2.gitee.io/shier_jinghuang/shier_jinghuang/2022/09/08/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E5%AE%9E%E8%AE%AD/">https://im-so-scared-2.gitee.io/shier_jinghuang/shier_jinghuang/2022/09/08/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E5%AE%9E%E8%AE%AD/</a>
                </span>
            </div>
            <div class="reprint__notice">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-copyright">
                        版权声明:
                    </i>
                </span>
                <span class="reprint-info">
                    本博客所有文章除特別声明外，均采用
                    <a href="https://creativecommons.org/licenses/by/4.0/deed.zh" rel="external nofollow noreferrer" target="_blank">CC BY 4.0</a>
                    许可协议。转载请注明来源
                    <a href="/shier_jinghuang/about" target="_blank">十二惊惶</a>
                    !
                </span>
            </div>
        
    </div>

    <script async defer>
      document.addEventListener("copy", function (e) {
        let toastHTML = '<span>复制成功，请遵循本文的转载规则</span><button class="btn-flat toast-action" onclick="navToReprintStatement()" style="font-size: smaller">查看</a>';
        M.toast({html: toastHTML})
      });

      function navToReprintStatement() {
        $("html, body").animate({scrollTop: $("#reprint-statement").offset().top - 80}, 800);
      }
    </script>



            <div class="tag_share" style="display: block;">
                <div class="post-meta__tag-list" style="display: inline-block;">
                    
                        <div class="article-tag">
                            
                                <a href="/shier_jinghuang/tags/%E5%AE%9E%E8%AE%AD%E8%AE%B0%E5%BD%95/">
                                    <span class="chip bg-color">实训记录</span>
                                </a>
                            
                        </div>
                    
                </div>
                <div class="post_share" style="zoom: 80%; width: fit-content; display: inline-block; float: right; margin: -0.15rem 0;">
                    <link rel="stylesheet" type="text/css" href="/shier_jinghuang/libs/share/css/share.min.css">
<div id="article-share">

    
    <div class="social-share" data-sites="twitter,facebook,google,qq,qzone,wechat,weibo,douban,linkedin" data-wechat-qrcode-helper="<p>微信扫一扫即可分享！</p>"></div>
    <script src="/shier_jinghuang/libs/share/js/social-share.min.js"></script>
    

    

</div>

                </div>
            </div>
            
        </div>
    </div>

    

    

    

    

    

    

    

    

    

<article id="prenext-posts" class="prev-next articles">
    <div class="row article-row">
        
        <div class="article col s12 m6" data-aos="fade-up">
            <div class="article-badge left-badge text-color">
                <i class="fas fa-chevron-left"></i>&nbsp;上一篇</div>
            <div class="card">
                <a href="/shier_jinghuang/2022/09/08/%E7%AE%80%E5%8D%95%E6%96%87%E4%BB%B6%E4%BC%A0%E8%BE%93%E5%99%A8/">
                    <div class="card-image">
                        
                        
                        <img src="/shier_jinghuang/medias/featureimages/8.jpg" class="responsive-img" alt="计算机网络实训之简单文件传输系统器">
                        
                        <span class="card-title">计算机网络实训之简单文件传输系统器</span>
                    </div>
                </a>
                <div class="card-content article-content">
                    <div class="summary block-with-text">
                        
                            
                        
                    </div>
                    <div class="publish-info">
                        <span class="publish-date">
                            <i class="far fa-clock fa-fw icon-date"></i>2022-09-08
                        </span>
                        <span class="publish-author">
                            
                            <i class="fas fa-bookmark fa-fw icon-category"></i>
                            
                            <a href="/shier_jinghuang/categories/%E7%BD%91%E7%BB%9C%E5%B7%A5%E7%A8%8B%E7%9B%B8%E5%85%B3/" class="post-category">
                                    网络工程相关
                                </a>
                            
                            
                        </span>
                    </div>
                </div>
                
                <div class="card-action article-tags">
                    
                    <a href="/shier_jinghuang/tags/%E5%AE%9E%E8%AE%AD%E8%AE%B0%E5%BD%95/">
                        <span class="chip bg-color">实训记录</span>
                    </a>
                    
                    <a href="/shier_jinghuang/tags/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/">
                        <span class="chip bg-color">计算机网络</span>
                    </a>
                    
                    <a href="/shier_jinghuang/tags/FTP/">
                        <span class="chip bg-color">FTP</span>
                    </a>
                    
                </div>
                
            </div>
        </div>
        
        
        <div class="article col s12 m6" data-aos="fade-up">
            <div class="article-badge right-badge text-color">
                下一篇&nbsp;<i class="fas fa-chevron-right"></i>
            </div>
            <div class="card">
                <a href="/shier_jinghuang/2022/08/10/%E6%95%B0%E5%AD%A6%E5%BB%BA%E6%A8%A1%E5%9B%BD%E8%B5%9B%E9%80%89%E6%8B%94/">
                    <div class="card-image">
                        
                        
                        <img src="/shier_jinghuang/medias/featureimages/4.jpg" class="responsive-img" alt="数学建模：综合选拔题">
                        
                        <span class="card-title">数学建模：综合选拔题</span>
                    </div>
                </a>
                <div class="card-content article-content">
                    <div class="summary block-with-text">
                        
                            
                        
                    </div>
                    <div class="publish-info">
                            <span class="publish-date">
                                <i class="far fa-clock fa-fw icon-date"></i>2022-08-10
                            </span>
                        <span class="publish-author">
                            
                            <i class="fas fa-bookmark fa-fw icon-category"></i>
                            
                            <a href="/shier_jinghuang/categories/%E4%B8%AA%E4%BA%BA/" class="post-category">
                                    个人
                                </a>
                            
                            
                        </span>
                    </div>
                </div>
                
                <div class="card-action article-tags">
                    
                    <a href="/shier_jinghuang/tags/%E6%95%B0%E5%AD%A6%E5%BB%BA%E6%A8%A1/">
                        <span class="chip bg-color">数学建模</span>
                    </a>
                    
                </div>
                
            </div>
        </div>
        
    </div>
</article>

</div>



<!-- 代码块功能依赖 -->
<script type="text/javascript" src="/shier_jinghuang/libs/codeBlock/codeBlockFuction.js"></script>


  <!-- 是否加载使用自带的 prismjs. -->
  <script type="text/javascript" src="/shier_jinghuang/libs/prism/prism.min.js"></script>


<!-- 代码语言 -->

<script type="text/javascript" src="/shier_jinghuang/libs/codeBlock/codeLang.js"></script>


<!-- 代码块复制 -->

<script type="text/javascript" src="/shier_jinghuang/libs/codeBlock/codeCopy.js"></script>


<!-- 代码块收缩 -->

<script type="text/javascript" src="/shier_jinghuang/libs/codeBlock/codeShrink.js"></script>



    </div>
    <div id="toc-aside" class="expanded col l3 hide-on-med-and-down">
        <div class="toc-widget card" style="background-color: white;">
            <div class="toc-title"><i class="far fa-list-alt"></i>&nbsp;&nbsp;目录</div>
            <div id="toc-content"></div>
        </div>
    </div>
</div>

<!-- TOC 悬浮按钮. -->

<div id="floating-toc-btn" class="hide-on-med-and-down">
    <a class="btn-floating btn-large bg-color">
        <i class="fas fa-list-ul"></i>
    </a>
</div>


<script src="/shier_jinghuang/libs/tocbot/tocbot.min.js"></script>
<script>
    $(function () {
        tocbot.init({
            tocSelector: '#toc-content',
            contentSelector: '#articleContent',
            headingsOffset: -($(window).height() * 0.4 - 45),
            collapseDepth: Number('0'),
            headingSelector: 'h2, h3, h4'
        });

        // Set scroll toc fixed.
        let tocHeight = parseInt($(window).height() * 0.4 - 64);
        let $tocWidget = $('.toc-widget');
        $(window).scroll(function () {
            let scroll = $(window).scrollTop();
            /* add post toc fixed. */
            if (scroll > tocHeight) {
                $tocWidget.addClass('toc-fixed');
            } else {
                $tocWidget.removeClass('toc-fixed');
            }
        });

        
        /* 修复文章卡片 div 的宽度. */
        let fixPostCardWidth = function (srcId, targetId) {
            let srcDiv = $('#' + srcId);
            if (srcDiv.length === 0) {
                return;
            }

            let w = srcDiv.width();
            if (w >= 450) {
                w = w + 21;
            } else if (w >= 350 && w < 450) {
                w = w + 18;
            } else if (w >= 300 && w < 350) {
                w = w + 16;
            } else {
                w = w + 14;
            }
            $('#' + targetId).width(w);
        };

        // 切换TOC目录展开收缩的相关操作.
        const expandedClass = 'expanded';
        let $tocAside = $('#toc-aside');
        let $mainContent = $('#main-content');
        $('#floating-toc-btn .btn-floating').click(function () {
            if ($tocAside.hasClass(expandedClass)) {
                $tocAside.removeClass(expandedClass).hide();
                $mainContent.removeClass('l9');
            } else {
                $tocAside.addClass(expandedClass).show();
                $mainContent.addClass('l9');
            }
            fixPostCardWidth('artDetail', 'prenext-posts');
        });
        
    });
</script>

    

</main>




    <footer class="page-footer bg-color">
    
        <link rel="stylesheet" href="/shier_jinghuang/libs/aplayer/APlayer.min.css">
<style>
    .aplayer .aplayer-lrc p {
        
        display: none;
        
        font-size: 12px;
        font-weight: 700;
        line-height: 16px !important;
    }

    .aplayer .aplayer-lrc p.aplayer-lrc-current {
        
        display: none;
        
        font-size: 15px;
        color: #42b983;
    }

    
    .aplayer.aplayer-fixed.aplayer-narrow .aplayer-body {
        left: -66px !important;
    }

    .aplayer.aplayer-fixed.aplayer-narrow .aplayer-body:hover {
        left: 0px !important;
    }

    
</style>
<div class="">
    
    <div class="row">
        <meting-js class="col l8 offset-l2 m10 offset-m1 s12"
                   server="netease"
                   type="playlist"
                   id="503838841"
                   fixed='true'
                   autoplay='false'
                   theme='#42b983'
                   loop='all'
                   order='random'
                   preload='auto'
                   volume='0.7'
                   list-folded='true'
        >
        </meting-js>
    </div>
</div>

<script src="/shier_jinghuang/libs/aplayer/APlayer.min.js"></script>
<script src="/shier_jinghuang/libs/aplayer/Meting.min.js"></script>

    

    <div class="container row center-align"
         style="margin-bottom: 0px !important;">
        <div class="col s12 m8 l8 copy-right">
            Copyright&nbsp;&copy;
            
                <span id="year">2019-2023</span>
            
            <a href="/shier_jinghuang/about" target="_blank">十二惊惶</a>
            |&nbsp;Powered by&nbsp;<a href="https://hexo.io/" target="_blank">Hexo</a>
            |&nbsp;Theme&nbsp;<a href="https://github.com/blinkfox/hexo-theme-matery" target="_blank">Matery</a>
            <br>
            
                &nbsp;<i class="fas fa-chart-area"></i>&nbsp;站点总字数:&nbsp;<span
                        class="white-color">289.6k</span>
            
            
            
                
            
            
                <span id="busuanzi_container_site_pv">
                &nbsp;|&nbsp;<i class="far fa-eye"></i>&nbsp;总访问量:&nbsp;
                    <span id="busuanzi_value_site_pv" class="white-color"></span>
            </span>
            
            
                <span id="busuanzi_container_site_uv">
                &nbsp;|&nbsp;<i class="fas fa-users"></i>&nbsp;总访问人数:&nbsp;
                    <span id="busuanzi_value_site_uv" class="white-color"></span>
            </span>
            
            <br>

            <!-- 运行天数提醒. -->
            
            <br>
            
        </div>
        <div class="col s12 m4 l4 social-link social-statis">
    <a href="https://github.com/blinkfox" class="tooltipped" target="_blank" data-tooltip="访问我的GitHub" data-position="top" data-delay="50">
        <i class="fab fa-github"></i>
    </a>



    <a href="mailto:1181062873@qq.com" class="tooltipped" target="_blank" data-tooltip="邮件联系我" data-position="top" data-delay="50">
        <i class="fas fa-envelope-open"></i>
    </a>







    <a href="tencent://AddContact/?fromId=50&fromSubId=1&subcmd=all&uin=1181062873" class="tooltipped" target="_blank" data-tooltip="QQ联系我: 1181062873" data-position="top" data-delay="50">
        <i class="fab fa-qq"></i>
    </a>







    <a href="/shier_jinghuang/atom.xml" class="tooltipped" target="_blank" data-tooltip="RSS 订阅" data-position="top" data-delay="50">
        <i class="fas fa-rss"></i>
    </a>

</div>
    </div>
</footer>

<div class="progress-bar"></div>


    <!-- 搜索遮罩框 -->
<div id="searchModal" class="modal">
    <div class="modal-content">
        <div class="search-header">
            <span class="title"><i class="fas fa-search"></i>&nbsp;&nbsp;搜索</span>
            <input type="search" id="searchInput" name="s" placeholder="请输入搜索的关键字"
                   class="search-input">
        </div>
        <div id="searchResult"></div>
    </div>
</div>

<script type="text/javascript">
$(function () {
    var searchFunc = function (path, search_id, content_id) {
        'use strict';
        $.ajax({
            url: path,
            dataType: "xml",
            success: function (xmlResponse) {
                // get the contents from search data
                var datas = $("entry", xmlResponse).map(function () {
                    return {
                        title: $("title", this).text(),
                        content: $("content", this).text(),
                        url: $("url", this).text()
                    };
                }).get();
                var $input = document.getElementById(search_id);
                var $resultContent = document.getElementById(content_id);
                $input.addEventListener('input', function () {
                    var str = '<ul class=\"search-result-list\">';
                    var keywords = this.value.trim().toLowerCase().split(/[\s\-]+/);
                    $resultContent.innerHTML = "";
                    if (this.value.trim().length <= 0) {
                        return;
                    }
                    // perform local searching
                    datas.forEach(function (data) {
                        var isMatch = true;
                        var data_title = data.title.trim().toLowerCase();
                        var data_content = data.content.trim().replace(/<[^>]+>/g, "").toLowerCase();
                        var data_url = data.url;
                        data_url = data_url.indexOf('/') === 0 ? data.url : '/' + data_url;
                        var index_title = -1;
                        var index_content = -1;
                        var first_occur = -1;
                        // only match artiles with not empty titles and contents
                        if (data_title !== '' && data_content !== '') {
                            keywords.forEach(function (keyword, i) {
                                index_title = data_title.indexOf(keyword);
                                index_content = data_content.indexOf(keyword);
                                if (index_title < 0 && index_content < 0) {
                                    isMatch = false;
                                } else {
                                    if (index_content < 0) {
                                        index_content = 0;
                                    }
                                    if (i === 0) {
                                        first_occur = index_content;
                                    }
                                }
                            });
                        }
                        // show search results
                        if (isMatch) {
                            str += "<li><a href='" + data_url + "' class='search-result-title'>" + data_title + "</a>";
                            var content = data.content.trim().replace(/<[^>]+>/g, "");
                            if (first_occur >= 0) {
                                // cut out 100 characters
                                var start = first_occur - 20;
                                var end = first_occur + 80;
                                if (start < 0) {
                                    start = 0;
                                }
                                if (start === 0) {
                                    end = 100;
                                }
                                if (end > content.length) {
                                    end = content.length;
                                }
                                var match_content = content.substr(start, end);
                                // highlight all keywords
                                keywords.forEach(function (keyword) {
                                    var regS = new RegExp(keyword, "gi");
                                    match_content = match_content.replace(regS, "<em class=\"search-keyword\">" + keyword + "</em>");
                                });

                                str += "<p class=\"search-result\">" + match_content + "...</p>"
                            }
                            str += "</li>";
                        }
                    });
                    str += "</ul>";
                    $resultContent.innerHTML = str;
                });
            }
        });
    };

    searchFunc('/shier_jinghuang/search.xml', 'searchInput', 'searchResult');
});
</script>

    <!-- 白天和黑夜主题 -->
<div class="stars-con">
    <div id="stars"></div>
    <div id="stars2"></div>
    <div id="stars3"></div>  
</div>

<script>
    function switchNightMode() {
        $('<div class="Cuteen_DarkSky"><div class="Cuteen_DarkPlanet"></div></div>').appendTo($('body')),
        setTimeout(function () {
            $('body').hasClass('DarkMode') 
            ? ($('body').removeClass('DarkMode'), localStorage.setItem('isDark', '0'), $('#sum-moon-icon').removeClass("fa-sun").addClass('fa-moon')) 
            : ($('body').addClass('DarkMode'), localStorage.setItem('isDark', '1'), $('#sum-moon-icon').addClass("fa-sun").removeClass('fa-moon')),
            
            setTimeout(function () {
            $('.Cuteen_DarkSky').fadeOut(1e3, function () {
                $(this).remove()
            })
            }, 2e3)
        })
    }
</script>

    <!-- 回到顶部按钮 -->
<div id="backTop" class="top-scroll">
    <a class="btn-floating btn-large waves-effect waves-light" href="#!">
        <i class="fas fa-arrow-up"></i>
    </a>
</div>


    <script src="/shier_jinghuang/libs/materialize/materialize.min.js"></script>
    <script src="/shier_jinghuang/libs/masonry/masonry.pkgd.min.js"></script>
    <script src="/shier_jinghuang/libs/aos/aos.js"></script>
    <script src="/shier_jinghuang/libs/scrollprogress/scrollProgress.min.js"></script>
    <script src="/shier_jinghuang/libs/lightGallery/js/lightgallery-all.min.js"></script>
    <script src="/shier_jinghuang/js/matery.js"></script>

    

    

    <!-- 雪花特效 -->
    

    <!-- 鼠标星星特效 -->
    

     
        <script src="https://ssl.captcha.qq.com/TCaptcha.js"></script>
        <script src="/shier_jinghuang/libs/others/TencentCaptcha.js"></script>
        <button id="TencentCaptcha" data-appid="xxxxxxxxxx" data-cbfn="callback" type="button" hidden></button>
    

    <!-- Baidu Analytics -->

    <!-- Baidu Push -->

<script>
    (function () {
        var bp = document.createElement('script');
        var curProtocol = window.location.protocol.split(':')[0];
        if (curProtocol === 'https') {
            bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
        } else {
            bp.src = 'http://push.zhanzhang.baidu.com/push.js';
        }
        var s = document.getElementsByTagName("script")[0];
        s.parentNode.insertBefore(bp, s);
    })();
</script>

    
    <script src="/shier_jinghuang/libs/others/clicklove.js" async="async"></script>
    
    
    <script async src="/shier_jinghuang/libs/others/busuanzi.pure.mini.js"></script>
    

    

    

    <!--腾讯兔小巢-->
    
    

    

    

    
    <script src="/shier_jinghuang/libs/instantpage/instantpage.js" type="module"></script>
    

</body>

</html>
